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:
Para esto necesitamos cuatro cosas:
PostManager
agregando toda la lógica del negocio necesaria.PostController::viewAction()
.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.
Aquí agregaremos dos métodos:
getCommentCountStr()
dará formato al contador de comentarios para
una publicación dada (ejemplo, "No hay comentarios", "1 comentario", "2 comentarios",
etc.)addCommentToPost()
se usará para agregar nuevos comentarios a una
publicación.<?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();
}
}
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']); ?>">
<< 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>