Frontend

Now that we have our API sending back the comments for each entry on the user's wall, we need to adapt the client code to do two things. First we create a new form and put it beneath each entry so that users can comment on stuff. The second thing we have to do is show the comments made by users beneath each entry. Let's see the following folder structure for the client code:

Frontend

Adding the Comment.php file

As usual we need to create an entity to store the data related with a comment. The entity itself is really simple, just a bunch of getters and setters. The only difference now is that we need to store a user entity inside the comment entity that will be the author data.

namespace WallEntity;

use ZendStdlibHydratorClassMethods;
use UsersEntityUser;

These two lines are the namespace and the declaration of the ClassMethod hydrator we are going to use to populate a User entity.

class Comment
{
    protected $id = null;
    protected $user = null;
    protected $comment = null;
    protected $createdAt = null;
    protected $updatedAt = null;
    
    public function setUser($user)
    {
        $hydrator = new ClassMethods();
        
        $this->user = $hydrator->hydrate($user, new User());
    }

    // MORE GETTERS AND SETTERS HERE
}

This is important code of the entity, for brevity the rest of the getters and setters are removed here, but you can check the code of this chapter if you want to see the full class.

The setUser() method is responsible for populating a User instance with the ClassMethod hydrator.

Adapting the Status.php file

Now we need to modify the entities we had for each content type to hold an array of possible comments. We are also going to store the type of the content itself to be able to send it to the API while commenting.

use ZendStdlibHydratorClassMethods;

Again, as we have to hydrate the comments we declare ClassMethods.

const COMMENT_TYPE_ID = 1;

This is the constant that will hold the type of content as you can see, it is exactly the same as the one we have on the API side.

protected $comments = null;

We need to add a new property in the class to be able to hold the array of comments provided by the API.

public function setComments($comments)
{ 
    $hydrator = new ClassMethods();
    
    foreach ($comments as $c) {
        $this->comments[] = $hydrator->hydrate($c, new Comment());
    }
}

This is the setter for the comments; as you can see we iterate over the comments, if any, and populate a new Comment instance appending it to the $comments property.

public function getComments()
{
    return $this->comments;
}

public function getType()
{
    return self::COMMENT_TYPE_ID;
}

Finally, we add two getters to the class; the first will return the comments and the second, COMMENT_TYPE_ID, will hold the type for this specific content.

Modifying the Image.php and Link.php file

The changes we have to do in these two entities are exactly the same as the ones we made on the status, the only difference being the number stored in the constant, COMMENT_TYPE_ID, which will be a two for Image.php and a three for Link.php.

As you can see, we are duplicating the code in the entities and it makes sense to make the entities to extend from a base entity and put the common code in the base entity. This task can be done by you as an exercise.

Adding the CommentForm.php file

The form we need to allow the users to add comments is really simple. We are going to have a textbox where users will put the comment on which itself. We will also have a couple of hidden fields that will hold the type of content we are commenting, and the ID of the entry we are commenting. Thanks to the hidden fields, the API will be able to associate the comment with the corresponding entry.

The structure of the file is the same as the one we have on other forms, so we will jump straight to the code we have on the constructor to see the fields we have.

parent::__construct('comment-content'),

$this->setAttribute('method', 'post'),
$this->setAttribute('class', 'well input-append'),

$this->add(array(
    'name' => 'comment',
    'type'  => 'ZendFormElementText',
    'attributes' => array(
        'class' => 'span11',
        'placeholder' => 'Write a comment here...'
    ),
));
$this->add(array(
    'name' => 'type',
    'type'  => 'ZendFormElementHidden',
));
$this->add(array(
    'name' => 'entry_id',
    'type'  => 'ZendFormElementHidden',
));
$this->add(array(
    'type' => 'ZendFormElementCsrf'
));
$this->add(array(
    'name' => 'submit',
    'attributes' => array(
        'type'  => 'submit',
        'value' => 'Submit',
        'class' => 'btn'
    ),
));

As you can see, the form is really simple, and we just add the fields we mentioned before with the usual Cross Site Request Forgery (CSRF) protection and the submit button.

Adding the comment-content-form.phtml file

The content of the view for the form is similar to the one we saw before; you can see the following code of the partial view that will be inserted in index.phtml view to print the form:

<?php $form = $this->form; ?>
<?php $form->prepare(); ?>
<?php echo $this->form()->openTag($form) ?>
<!-- Comment input text -->
<?php echo $this->formElement($form->get('comment')); ?>

<!-- Submit button -->
<?php echo $this->formElement(
    $form->get('type')->setValue($type)
); ?>
<?php echo $this->formElement(
    $form->get('entry_id')->setValue($entryId)
); ?>
<?php echo $this->formElement($form->get('submit')); ?>

<!-- Error message -->
<?php echo $this->formElementErrors($form->get('comment')); ?>

<!-- CSRF -->
<?php echo $this->formElement($form->get('csrf')); ?>
<?php echo $this->formElementErrors($form->get('csrf')); ?>

<?php echo $this->form()->closeTag() ?>

Notice that we are setting the values of the hidden fields based in two variables, $type and $entryId, that we expect.

Modifying the IndexController.php file

The changes we have to do on the controller are simple and short. Let's review the changes in the indexAction() method.

use WallFormsCommentForm;

First, we need to declare the usage of CommentForm by adding the following line at the top:

$commentForm = new CommentForm();

Then we need to create an instance of the form; we will do that in the block of code where we create the other forms.

if (array_key_exists('comment', $data)) {
    $result = $this->createComment($commentForm, $user, $data);
}

Now, in the section where we inspect the POST request, we need to add a new block to check if the user is trying to create a comment, and then redirect the request to the proper method.

case $result instanceOf CommentForm:
    $commentForm = $result;
    break;

When we process the form results, we need to add a new case in the switch statement to check the return value of the createComment() method.

$commentForm->setAttribute(
    'action', 
    $this->url()->fromRoute(
        'wall', 
        array('username' => $user->getUsername())
    )
);

This piece of code should be added next to the block where we set the attributes to the other forms; it is exactly the same but of different form.

$viewData['commentContentForm'] = $commentForm;

This is the final line we have to add in this method to pass the form to the view and be able to print it.

As this form is really simple, the createComment() method will call the processSimpleForm() parent method.

protected function createComment($form, $user, array $data)
{
    return $this->processSimpleForm($form, $user, $data);
}

Extending the index.phtml file

This is the last file we have to modify to make everything work. We are going to add a block of code right after printing the content of each entry to print the comments, if any, and also to insert the comment form.

<?php if ($entry->getComments() !== NULL) : ?>
    <ul class="post-list">
        <?php foreach ($entry->getComments() as $i => $c) : ?>
            <li class="post">
                <section>
                    <a href="#" class="pull-left thumbnail">
                        <img src="#" />
                    </a>
                    <div class="post-body">
                        <h4 class="post-heading">
                            <a href="#">NAME OF USER</a>
                        </h4>
                        <p><?php echo $c->getComment() ?></p>
                    </div>
                </section>
            </li>
        <?php endforeach; ?>
    </ul>
<?php endif; ?>
<?php echo $this->partial(
    'forms/comment-content-form.phtml', 
    array(
        'form' => $commentContentForm, 
        'type' => $entry->getType(), 
        'entryId' => $entry->getId())
); ?>

The code you can see here is a simplified version of the real one, otherwise it will not be readable. As you can see, if there are comments, we iterate over them and print each one putting the avatar of the user, hardcoded for now, and also the name of the user and the content of the comment. Finally, we call the partial that will render the comment form and pass the type of entry and the entry ID to populate it on the hidden fields.

The following screenshot shows how the wall looks like now:

Extending the index.phtml file
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset