A free and open-source book on ZF3 for beginners


12.12. Реализация просмотра поста

В этом разделе мы создадим действие контроллера и соответствующий шаблон представления, которые позволят посетителям сайта просмотреть определенный пост, набрав в адресной строке браузера URL http://localhost/posts/view/<id>, где <id> - уникальный идентификатор поста.

На этой странице также можно будет добавлять комментарии к посту, используя форму, находящуюся в нижней части страницы. Пример того, чего мы хотим добиться, показан на рисунке 12.9 ниже:

Рисунок 12.9. Страница View Post Рисунок 12.9. Страница View Post

Итак, нам понадобится сделать следующее:

12.12.1. Добавление CommentForm

Первым делом мы реализуем форму 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 содержит поля автора и комментария и кнопку отправки формы.

Так как мы уже детально рассмотрели формы в предыдущих главах, мы не будем разбирать представленный выше код.

12.12.2. Изменение PostManager

В этот класс мы добавим два метода:

<?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();
    }
}

12.12.3. Добавление действия контроллера и шаблона представления

Теперь добавьте метод 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']); ?>">
    &lt;&lt; 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>   

Top