В этом разделе мы создадим действие контроллера и соответствующий шаблон представления, которые позволят посетителям сайта просмотреть определенный пост, набрав в адресной строке браузера URL http://localhost/posts/view/<id>, где <id> - уникальный идентификатор поста.
На этой странице также можно будет добавлять комментарии к посту, используя форму, находящуюся в нижней части страницы. Пример того, чего мы хотим добиться, показан на рисунке 12.9 ниже:
Итак, нам понадобится сделать следующее:
PostManager
и добавить необходимую бизнес-логику;PostController::viewAction()
;Первым делом мы реализуем форму CommentForm
, которая позволит добавлять комментарий
к посту. Создайте файл CommentForm.php в каталоге Form под корневым каталогом
модуля. Поместите в него следующее содержимое:
<?php
namespace Application\Form;
use Zend\Form\Form;
use Zend\InputFilter\InputFilter;
/**
* Эта форма используется для сбора данных комментария.
*/
class CommentForm extends Form
{
// Конструктор.
public function __construct()
{
// Определяем имя формы
parent::__construct('comment-form');
// Задаем POST-метод для этой формы
$this->setAttribute('method', 'post');
$this->addElements();
$this->addInputFilter();
}
// Этот метод добавляет элементы к форме (поля ввода и кнопку отправки формы).
protected function addElements()
{
// Добавляем поле "author"
$this->add([
'type' => 'text',
'name' => 'author',
'attributes' => [
'id' => 'author'
],
'options' => [
'label' => 'Author',
],
]);
// Добавляем поле "comment"
$this->add([
'type' => 'textarea',
'name' => 'comment',
'attributes' => [
'id' => 'comment'
],
'options' => [
'label' => 'Comment',
],
]);
// Добавляем кнопку отправки формы
$this->add([
'type' => 'submit',
'name' => 'submit',
'attributes' => [
'value' => 'Save',
'id' => 'submitbutton',
],
]);
}
// Этот метод создает фильтр входных данных (используется для фильтрации/валидации).
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
],
],
],
]);
}
}
Как видите из данного кода, форма CommentForm
содержит поля автора и комментария и кнопку отправки формы.
Так как мы уже детально рассмотрели формы в предыдущих главах, мы не будем разбирать представленный выше код.
В этот класс мы добавим два метода:
getCommentCountStr()
будет форматировать строку количества комментариев для заданного
поста (например, "No comments", "1 comment", "2 comments" и т.д.);addCommentToPost()
будет использоваться для добавления нового комментария к посту.<?php
//...
/**
* Сервис PostManager отвечает за дополнение новых постов.
*/
class PostManager
{
//...
// Возвращает количество комментариев для заданного поста в виде должным образом отформатированной строки.
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';
}
// Этот метод добавляет новый комментарий к посту.
public function addCommentToPost($post, $data)
{
// Создаем новую сущность Comment.
$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);
// Добавляем сущность к менеджеру сущность.
$this->entityManager->persist($comment);
// Применяем изменения.
$this->entityManager->flush();
}
}
Теперь добавьте метод PostController::viewAction()
и поместите в него следующий код:
<?php
//...
use Application\Form\CommentForm;
use Application\Entity\Comment;
class PostController extends AbstractActionController
{
/**
* Это действие отображает страницу "View 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);
// Создаем форму.
$form = new CommentForm();
// Проверяем, является ли пост POST-запросом.
if($this->getRequest()->isPost()) {
// Получаем POST-данные.
$data = $this->params()->fromPost();
// Заполняем форму данными.
$form->setData($data);
if($form->isValid()) {
// Получаем валадированные данные формы.
$data = $form->getData();
// Используем менеджер постов для добавления нового комментарий к посту.
$this->postManager->addCommentToPost($post, $data);
// Снова перенаправляем пользователя на страницу "view".
return $this->redirect()->toRoute('posts', ['action'=>'view', 'id'=>$postId]);
}
}
// Визуализируем шаблон представления.
return new ViewModel([
'post' => $post,
'commentCount' => $commentCount,
'form' => $form,
'postManager' => $this->postManager
]);
}
}
Наконец, добавим файл шаблона представления view.phtml и заполним его следующим содержимым:
<?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>