A free and open-source book on ZF3 for beginners

Translation into this language is not yet finished. You can help this project by translating the chapters and contributing your changes.

12.12. Implementar la Vista Previa para la Publicación

En esta sección crearemos una acción en el controlador y su plantilla de vista correspondiente que permitirá a los visitantes del sitio tener una vista previa de determinada publicación ingresando la siguiente URL en la barra de navegación del navegador web: http://localhost/posts/view/<id>, donde <id> es el identificador único para la publicación.

Además, la página permitirá agregar comentarios a la publicación usando un formulario ubicado en la parte baja de la página. Un ejemplo de lo que estamos intentado hacer se muestra abajo en la figura 12.9:

Figure 12.9. Página Vista de Publicación Figure 12.9. Página Vista de Publicación

Para esto necesitamos cuatro cosas:

12.12.1. Agregar el CommentForm

Primero implementaremos el formulario CommentForm que permitirá agregar un comentario a una publicación. Creamos el archivo CommentForm.php en la carpeta Form dentro de la carpeta fuente del módulo. Colocamos el siguiente código dentro del archivo:

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

Como se puede ver del código de arriba, el formulario CommentForm contiene los campos autor y comentario además del botón Submit.

Como se explico en detalla el funcionamiento de los formularios en capítulos anteriores no explicaremos el código de arriba a profundidad.

12.12.2. Modificar el PostManager

Aquí agregaremos dos métodos:

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

12.12.3. Agregar la Acción en el Controlador y la Plantilla de Vista

Ahora agregamos el método PostController::viewAction() colocando el siguiente código:

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

Finalmente agregamos el archivo con la plantilla de vista view.phtml colocando el siguiente código dentro del archivo:

<?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