In this section, we will create controller's action and its corresponding view template that would allow site visitors to preview certain post by entering the following URL in browser's navigation bar: http://localhost/posts/view/<id>, where <id> is the unique identifier of the post.
The page will also allow to add comments to the post using the form located at the bottom of the page. For example of what we are trying to achive, please look at the figure 12.9 below:
So, for this we need four things:
PostManager
and add all necessary business logic;PostController::viewAction()
controller's action;First, we implement the CommentForm
form that will allow to add a comment to a post.
Create the CommentForm.php file in Form directory under module's source directory.
Put the following content into the file:
<?php
namespace Application\Form;
use Zend\Form\Form;
use Zend\InputFilter\InputFilter;
/**
* This form is used to collect comment data.
*/
class CommentForm extends Form
{
// Constructor.
public function __construct()
{
// Define form name
parent::__construct('comment-form');
// Set POST method for this form
$this->setAttribute('method', 'post');
$this->addElements();
$this->addInputFilter();
}
// This method adds elements to form (input fields and submit button).
protected function addElements()
{
// Add "author" field
$this->add([
'type' => 'text',
'name' => 'author',
'attributes' => [
'id' => 'author'
],
'options' => [
'label' => 'Author',
],
]);
// Add "comment" field
$this->add([
'type' => 'textarea',
'name' => 'comment',
'attributes' => [
'id' => 'comment'
],
'options' => [
'label' => 'Comment',
],
]);
// Add the submit button
$this->add([
'type' => 'submit',
'name' => 'submit',
'attributes' => [
'value' => 'Save',
'id' => 'submitbutton',
],
]);
}
// This method creates input filter (used for form filtering/validation).
private function addInputFilter()
{
$inputFilter = new InputFilter();
$this->setInputFilter($inputFilter);
$inputFilter->add([
'name' => 'author',
'required' => true,
'filters' => [
['name' => 'StringTrim'],
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'min' => 1,
'max' => 128
],
],
],
]);
$inputFilter->add([
'name' => 'comment',
'required' => true,
'filters' => [
['name' => 'StripTags'],
],
'validators' => [
[
'name' => 'StringLength',
'options' => [
'min' => 1,
'max' => 4096
],
],
],
]);
}
}
As you see from the code above, the CommentForm
form contains the author, comment fields, and the Submit button.
Since we covered forms in details in previous chapters, here we do not explain the code presented above deeply.
Here, we add two methods:
getCommentCountStr()
method will format the comment count string for the given post
(e.g., "No comments", "1 comment", "2 comments", etc.)addCommentToPost()
method will be used for adding a new comment to post.<?php
//...
/**
* The PostManager service is responsible for adding new posts.
*/
class PostManager
{
//...
// Returns count of comments for given post as properly formatted string.
public function getCommentCountStr($post)
{
$commentCount = count($post->getComments());
if ($commentCount == 0)
return 'No comments';
else if ($commentCount == 1)
return '1 comment';
else
return $commentCount . ' comments';
}
// This method adds a new comment to post.
public function addCommentToPost($post, $data)
{
// Create new Comment entity.
$comment = new Comment();
$comment->setPost($post);
$comment->setAuthor($data['author']);
$comment->setContent($data['comment']);
$currentDate = date('Y-m-d H:i:s');
$comment->setDateCreated($currentDate);
// Add the entity to entity manager.
$this->entityManager->persist($comment);
// Apply changes.
$this->entityManager->flush();
}
}
Now, add the PostController::viewAction()
method and put the following code there:
<?php
//...
use Application\Form\CommentForm;
use Application\Entity\Comment;
class PostController extends AbstractActionController
{
/**
* This action displays the "View Post" page allowing to see the post title
* and content. The page also contains a form allowing
* to add a comment to post.
*/
public function viewAction()
{
$postId = $this->params()->fromRoute('id', -1);
$post = $this->entityManager->getRepository(Post::class)
->findOneById($postId);
if ($post == null) {
$this->getResponse()->setStatusCode(404);
return;
}
$commentCount = $this->postManager->getCommentCountStr($post);
// Create the form.
$form = new CommentForm();
// Check whether this post is a POST request.
if($this->getRequest()->isPost()) {
// Get POST data.
$data = $this->params()->fromPost();
// Fill form with data.
$form->setData($data);
if($form->isValid()) {
// Get validated form data.
$data = $form->getData();
// Use post manager service to add new comment to post.
$this->postManager->addCommentToPost($post, $data);
// Redirect the user again to "view" page.
return $this->redirect()->toRoute('posts', ['action'=>'view', 'id'=>$postId]);
}
}
// Render the view template.
return new ViewModel([
'post' => $post,
'commentCount' => $commentCount,
'form' => $form,
'postManager' => $this->postManager
]);
}
}
Finally, add the view.phtml view template file and put the following content there:
<?php
$form = $this->form;
$form->get('author')->setAttributes([
'class'=>'form-control',
'placeholder'=>'Author\'s name'
]);
$form->get('comment')->setAttributes([
'class'=>'form-control',
'rows'=>6,
'placeholder'=>'Text'
]);
$form->get('submit')->setAttributes(['class'=>'btn btn-primary']);
$form->prepare();
?>
<a href="
<?= $this->url('application', ['action'=>'index']); ?>">
<< Back to list of posts
</a>
<h1>
<?= $this->escapeHtml($post->getTitle()); ?>
</h1>
<p class="comments-header">
<?= $this->escapeHtml($postManager->getCommentCountStr($post)); ?> |
<a href="#comment">
Add new comment
</a>
</p>
<p>
Published: <?= $this->escapeHtml(date('jS \of F Y', strtotime($post->getDateCreated()))); ?>
| Tags: <?= $this->escapeHtml($postManager->convertTagsToString($post)); ?>
</p>
<p>
<?= $this->escapeHtml($post->getContent()); ?>
</p>
<h3><?= $this->escapeHtml($postManager->getCommentCountStr($post)); ?></h3>
<?php foreach ($post->getComments() as $comment): ?>
<hr>
<p>
<?= $this->escapeHtml($comment->getAuthor()) ?> on
<?= $this->escapeHtml($comment->getDateCreated()); ?>
</p>
<p>
<?= $this->escapeHtml($comment->getContent()); ?>
</p>
<?php endforeach; ?>
<hr>
<a name="comment"></a>
<h3>Leave Reply</h3>
<div class="row">
<div class="col-md-8">
<?= $this->form()->openTag($form); ?>
<div class="form-group">
<?= $this->formLabel($form->get('author')); ?>
<?= $this->formElement($form->get('author')); ?>
<?= $this->formElementErrors($form->get('author')); ?>
</div>
<div class="form-group">
<?= $this->formLabel($form->get('comment')); ?>
<?= $this->formElement($form->get('comment')); ?>
<?= $this->formElementErrors($form->get('comment')); ?>
</div>
<?= $this->formElement($form->get('submit')); ?>
<?= $this->form()->closeTag(); ?>
</div>
</div>