In this tutorial, we will add functions for viewing topics of the forum, adding topic, posting replies. At the end of this tutorial, you will also be able to download the full source code of this forum.
Now we have completed the section for forum index page. However the whole forum does not really work yet.
The first thing we are going to build in this tutorial is the function for showing/viewing/adding topics. These functions are handled by the same controller (TopicsController).
Copy following to "app/Controller/TopicsController.php":
<?php
App::uses('AppController', 'Controller');
class TopicsController extends AppController {
public $components = array('Paginator');
public function beforeFilter() {
$this->Auth->allow('index','view');
}
public function index($forumId=null) {
if (!$this->Topic->Forum->exists($forumId)) {
throw new NotFoundException(__('Invalid forum'));
}
$forum = $this->Topic->Forum->read(null,$forumId);
$this->set('forum',$forum);
$this->Paginator->settings['contain'] = array('User','Post'=>array('User'));
$this->set('topics', $this->Paginator->paginate());
}
public function add() {
$forums = $this->Topic->Forum->find('list');
if ($this->request->is('post')) {
$this->request->data['Topic']['user_id'] = $this->Auth->user('id');
if ($this->Topic->save($this->request->data)) {
$this->Session->setFlash(__('Topic has been created'));
$this->redirect('/');
}
}
$this->set('forums',$forums);
}
public function view($id) {
if (!$this->Topic->exists($id)) {
throw new NotFoundException(__('Invalid topic'));
}
$topic = $this->Topic->read(null,$id);
$forum = $this->Topic->Forum->read(null,$topic['Topic']['forum_id']);
$this->Paginator->settings['Post']['conditions'] = array('Post.topic_id'=>$topic['Topic']['id']);
$this->Paginator->settings['Post']['contain'] = array('User');
$this->Paginator->settings['Post']['order'] = array('Post.id'=>'DESC');
$this->set('topics', $this->Paginator->paginate('Post'));
$this->set('topic', $topic);
$this->set('forum', $forum);
$this->set('posts', $this->Paginator->paginate('Post'));
}
}
Let us take a look at each function:
Now let us create view files according to the TopicsController's functions.
"app/View/Topics/index.ctp":
<div class="row">
<div class="col-lg-12">
<ol class="breadcrumb">
<li>
<?php echo $this->Html->link(__('Forum'),'/')?>
</li>
<li class="active">
<?php echo $forum['Forum']['name']?>
</li>
</ol>
</div>
</div>
<div class="row">
<div class="col-lg-4">
<p style="font-weight:bold;">
<?php
echo $this->Paginator->counter(
'Showing {:start} - {:end} of {:count}'
);
?>
</p>
</div>
<div class="col-lg-8">
<p class="text-right">
<?php echo $this->Html->link(__('Create Topic'),array('action'=>'add'),array('class'=>'btn btn-primary'))?>
</p>
</div>
</div>
<div class="row">
<div class="col-lg-12 ">
<table class="table table-bordered">
<thead>
<tr>
<th colspan=2>Topic</th>
<th>Author</th>
<th>Created</th>
<th>Posts</th>
<th>Activity</th>
</tr>
</thead>
<tbody>
<?php foreach ($topics as $topic): ?>
<tr>
<td> </td>
<td>
<?php
echo $this->Html->link($topic['Topic']['name'],
array('controller'=>'topics','action'=>'view',$topic['Topic']['id']));
?>
</td>
<td><?php
echo $this->Html->link($topic['User']['username'],
array('controller'=>'users','action'=>'profile',$topic['User']['id']));
?>
</td>
<td><?php
echo $this->Time->timeAgoInWords($topic['Topic']['created']);
?>
</td>
<td>
<?php
echo count($topic['Post']);
?>
</td>
<td>
<?php
if(count($topic['Post'])>0) {
$post = $topic['Post'][0];
echo $this->Time->timeAgoInWords($post['created']);
echo ' <small>by</small> ';
echo $this->Html->link($post['User']['username'],array('controller'=>'users',
'action'=>'profile',
$post['User']['id']));
}
?>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class="pull-right">
<?php
echo $this->element('paginator');
?>
</div>
</div>
</div>
Now if you click on the topic's title from forum index page, you should be able to see page as below:
"app/View/Topics/view.ctp":
<div class="row">
<div class="col-lg-12">
<ol class="breadcrumb">
<li>
<?php echo $this->Html->link(__('Forum'),'/')?>
</li>
<li>
<?php echo $this->Html->link($forum['Forum']['name'],array('controller'=>'topics','action'=>'index',$forum['Forum']['id']))?>
</li>
<li class="active">
<?php echo $topic['Topic']['name'];?>
</li>
</ol>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<p class="lead">
<?php echo $topic['Topic']['content'];?>
</p>
</div>
<div class="col-lg-4">
<p class="text-right">
<?php echo $this->Html->link(__('Create Topic'),array('action'=>'add'),
array('class'=>'btn btn-primary'))?>
<?php echo $this->Html->link(__('Post Reply'),array('controller'=>'posts','action'=>'add',$topic['Topic']['id']),
array('class'=>'btn btn-primary'))?>
</p>
</div>
</div>
<div class="row">
<div class="col-lg-4">
<p style="font-weight: bold;">
<?php
echo $this->Paginator->counter(
'Showing {:start} - {:end} of {:count}'
);
?>
</p>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<table class="table table-bordered ">
<tbody>
<?php
foreach ($posts as $post) :
?>
<tr>
<td><small>
<?php
echo $this->Time->timeAgoInWords($post['Post']['created']);
?></small>
</td>
<td> </td>
</tr>
</tr>
<td width="150px">
<p>
<?php
echo $this->Html->link($post['User']['username'],
array('controller'=>'users','action'=>'profile',$post['User']['id']));
?>
</p>
<?php $hash = md5($post['User']['email']);?>
<img src="http://www.gravatar.com/avatar/<?php echo $hash;?>?s=100" >
</td>
<td>
<p>
<?php echo $post['Post']['content'];?>
</p>
</td>
</tr>
<?php endforeach;?>
</tbody>
</table>
<div class="pull-right">
<?php
echo $this->element('paginator');
?>
</div>
<div class="clearfix"></div>
<div class="well">
<h4><?php echo __('Quick Reply');?></h4>
<?php echo $this->Form->create('Post',array('url'=>array('controller'=>'posts','action'=>'add'),
'inputDefaults'=>array('label'=>false)));?>
<div class="form-group">
<?php echo $this->Form->textarea('content',array('class'=>'form-control','rows'=>5));?>
</div>
<?php echo $this->Form->hidden('topic_id',array('value'=>$topic['Topic']['id']));?>
<?php echo $this->Form->hidden('forum_id',array('value'=>$forum['Forum']['id']));?>
<?php echo $this->Form->submit(__('Post Reply'),array('class'=>'btn btn-primary'))?>
<?php echo $this->Form->end();?>
</div>
</div>
</div>
Now clicking on the topic's title from page above, you should be able to see page as below:
<div class="row">
<div class="col-lg-12">
<ol class="breadcrumb">
<li>
<?php echo $this->Html->link(__('Forum'),'/')?>
</li>
<li class="active">
<?php echo __('Create Topic');?>
</li>
</ol>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<p class="lead"><?php echo __('Create Topic');?></p>
<div class="well">
<?php echo $this->Form->create('Topic',array('class'=>'form-horizontal','inputDefaults'=>array('label'=>false)));?>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Title</label>
<div class="col-sm-10">
<?php echo $this->Form->input('name',array('class'=>'form-control'));?>
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Forum</label>
<div class="col-sm-10">
<?php echo $this->Form->input('forum_id',array('options'=>$forums, 'class'=>'form-control'));?>
</div>
</div>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Content</label>
<div class="col-sm-10">
<?php echo $this->Form->textarea('content',array('class'=>'form-control','rows'=>5));?>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<?php echo $this->Form->submit(__('Create'),array('class'=>'btn btn-primary'))?>
</div>
</div>
</form>
</div>
</div>
</div>
Now clicking on "Create Topic", you should be able to see page as below. The form should also let you create new topic:
Last piece of function we need is to allow users to post reply to the topic. This is handled by PostsController and its view files.
"app/Controller/PostsController.php":
<?php
App::uses('AppController', 'Controller');
class PostsController extends AppController {
public function add($topicId=null) {
if ($this->request->is('post')) {
$this->request->data['Post']['user_id'] = $this->Auth->user('id');
if ($this->Post->save($this->request->data)) {
$this->Session->setFlash(__('Post has been created'));
$this->redirect(array('controller'=>'topics','action'=>'view',$this->request->data['Post']['topic_id']));
}
} else {
if (!$this->Post->Topic->exists($topicId)) {
throw new NotFoundException(__('Invalid topic'));
}
$this->Post->Topic->recursive = -1;
$topic = $this->Post->Topic->read(null,$topicId);
$this->Post->Forum->recursive = -1;
$forum = $this->Post->Forum->read(null,$topic['Topic']['forum_id']);
$this->set('topic',$topic);
$this->set('forum',$forum);
}
}
}
"app/View/Posts/add.ctp":
<div class="row">
<div class="col-lg-12">
<ol class="breadcrumb">
<li>
<?php echo $this->Html->link(__('Forum'),'/')?>
</li>
<li>
<?php echo $this->Html->link($forum['Forum']['name'],array('controller'=>'topics','action'=>'index',$forum['Forum']['id']))?>
</li>
<li>
<?php echo $this->Html->link($topic['Topic']['name'],array('controller'=>'topics','action'=>'view',$topic['Topic']['id']))?>
</li>
<li class="active">
<?php echo __('Post Reply');?>
</li>
</ol>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<p class="lead"><?php echo __('Post Reply');?></p>
<div class="well">
<?php echo $this->Form->create('Post',array('class'=>'form-horizontal','inputDefaults'=>array('label'=>false)));?>
<div class="form-group">
<label for="inputPassword3" class="col-sm-2 control-label">Content</label>
<div class="col-sm-10">
<?php echo $this->Form->textarea('content',array('class'=>'form-control','rows'=>8));?>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<?php echo $this->Form->submit(__('Post Reply'),array('class'=>'btn btn-primary'))?>
</div>
</div>
<?php echo $this->Form->hidden('topic_id',array('value'=>$topic['Topic']['id']))?>
<?php echo $this->Form->hidden('forum_id',array('value'=>$forum['Forum']['id']))?>
<?php echo $this->Form->end();?>
</div>
</div>
</div>
With the completion above, now CapForum should be a fully working application. By clicking "Post Reply" you should be able to see page as below.
You can download CapForum's full source code from the link below:
We have completed the series of build a forum with CakePHP. As mentioned in first tutorial, this forum is not product ready. There are plenty of features you can add in. Such as adding a backend module, so admin is able to manage all aspects of the system. You are free to extend this application to your own use.
Hopefully this simple tutorial helped you with your development. If you like our post, please follow us on Twitter and help spread the word. We need your support to continue. If you have questions or find our mistakes in above tutorial, do leave a comment below to let us know.