In this section, we will implement the Edit Post page which contains the form allowing to edit the data of existing post, send new data to server and apply changes to database. Site visitor will be able to see the page by entering the following URL in browser's navigation bar: http://localhost/posts/edit/<id>, where <id> is the unique identifier of the post.
To implement this page we need the following things:
PostForm
form we created earlier (we just rename the Create button
caption into Save).updatePost()
method to the PostManager
service. The method would find the post by
ID in database and update its data;convertTagsToString()
method to the PostManager
service. This method would take the
post entity, and on output produce string containing comma-separated list of tags;PostController::editAction()
action method that would take user input, pass it
to models and return data for rendering;First, we add the updatePost()
and convertTagsToString()
methods to the PostManager
service
model as follows:
<?php
//...
class PostManager
{
//...
// This method allows to update data of a single post.
public function updatePost($post, $data)
{
$post->setTitle($data['title']);
$post->setContent($data['content']);
$post->setStatus($data['status']);
// Add tags to post
$this->addTagsToPost($data['tags'], $post);
// Apply changes to database.
$this->entityManager->flush();
}
// Converts tags of the given post to comma separated list (string).
public function convertTagsToString($post)
{
$tags = $post->getTags();
$tagCount = count($tags);
$tagsStr = '';
$i = 0;
foreach ($tags as $tag) {
$i ++;
$tagsStr .= $tag->getName();
if ($i < $tagCount)
$tagsStr .= ', ';
}
return $tagsStr;
}
}
Above, we have the updatePost()
method (lines 8-19) that takes an existing Post
entity,
the new title, content, status and the list of tags. It then updates entity's properties and
saves changes to database using flush()
method.
Note that the
updatePost()
method doesn't use thepersist()
method of entity manager, because here we have existing post, not a new one.
Then, we have the convertTagsToString()
method (lines 22-36) which takes the post, goes through
Tag
entities associated with the post and formats and returns the comma-separated list of tags.
Next, add the editAction()
to PostController
controller class as follows:
<?php
namespace Application\Controller;
//...
use Application\Form\PostForm;
use Application\Entity\Post;
class PostController extends AbstractActionController
{
// This action displays the page allowing to edit a post.
public function editAction()
{
// Create the form.
$form = new PostForm();
// Get post ID.
$postId = $this->params()->fromRoute('id', -1);
// Find existing post in the database.
$post = $this->entityManager->getRepository(Post::class)
->findOneById($postId);
if ($post == null) {
$this->getResponse()->setStatusCode(404);
return;
}
// 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 post to database.
$this->postManager->updatePost($post, $data);
// Redirect the user to "admin" page.
return $this->redirect()->toRoute('posts', ['action'=>'admin']);
}
} else {
$data = [
'title' => $post->getTitle(),
'content' => $post->getContent(),
'tags' => $this->postManager->convertTagsToString($post),
'status' => $post->getStatus()
];
$form->setData($data);
}
// Render the view template.
return new ViewModel([
'form' => $form,
'post' => $post
]);
}
}
In the code above, we extract the post ID using the fromRoute()
method of the params()
controller
plugin. Then we search for post having such ID using the findOneBy()
method provided by the
entity repository.
Then we check if this is a POST request. If this is the POST request, we fill in and validate the form
with POST data. Then we use the updatePost()
method of the PostManager
service.
Finally, create the application/post/edit.phtml file under the module's view directory. Place the following content there:
<?php
$form = $this->form;
$form->get('title')->setAttributes([
'class'=>'form-control',
'placeholder'=>'Enter post title here'
]);
$form->get('content')->setAttributes([
'class'=>'form-control',
'placeholder'=>'Type content here',
'rows'=>6
]);
$form->get('tags')->setAttributes([
'class'=>'form-control',
'placeholder'=>'comma, separated, list, of, tags'
]);
$form->get('status')->setAttributes([
'class'=>'form-control'
]);
$form->get('submit')->setAttributes(['class'=>'btn btn-primary']);
$form->get('submit')->setValue('Save');
$form->prepare();
?>
<h1>Edit Post</h1>
<p>
Please fill out the following form and click the *Save* button.
</p>
<div class="row">
<div class="col-md-6">
<?= $this->form()->openTag($form); ?>
<div class="form-group">
<?= $this->formLabel($form->get('title')); ?>
<?= $this->formElement($form->get('title')); ?>
<?= $this->formElementErrors($form->get('title')); ?>
</div>
<div class="form-group">
<?= $this->formLabel($form->get('content')); ?>
<?= $this->formElement($form->get('content')); ?>
<?= $this->formElementErrors($form->get('content')); ?>
</div>
<div class="form-group">
<?= $this->formLabel($form->get('tags')); ?>
<?= $this->formElement($form->get('tags')); ?>
<?= $this->formElementErrors($form->get('tags')); ?>
<p class="help-block">Separate tags with comma.</p>
</div>
<div class="form-group">
<?= $this->formLabel($form->get('status')); ?>
<?= $this->formElement($form->get('status')); ?>
<?= $this->formElementErrors($form->get('status')); ?>
</div>
<?= $this->formElement($form->get('submit')); ?>
<?= $this->form()->closeTag(); ?>
</div>
</div>
Now, if you open the URL http://localhost/posts/edit/<id> in your web browser, you should be able to see the Edit Post page that allows to edit an existing post (see the figure 12.8 below):
Clicking the Save button results in saving the changes to database.