This is very similar to adding and editing a post.
First up, we’re going to add the route so we can delete a post by creating the delete route into the view
child
routes.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
'delete' => [
//routeName: blog/view/delete
//route: /blog/:id[/slug]/delete
'type' => 'Literal',
'may_terminate' => true,
'options' => [
'route' => '/delete',
'defaults' => [
'module' => 'Blog',
'controller' => 'Blog\\Controller\\Post',
'action' => 'delete',
],
],
],
Next up, we’re using the following code for the delete.phtml
view.
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
/** @var Blog\Form\PostDeleteForm $form */
?>
<section>
<?php $form->prepare() ?>
<?= $this->form()->openTag($form) ?>
<?= $this->formRow($form->get('csrf')) ?>
<?= $this->formRow($form->get('submit[yes]')) ?>
<?= $this->formRow($form->get('submit[no]')) ?>
<?= $this->form()->closeTag($form) ?>
</section>
You’ll notice that this is different from the previous form pages (add/edit). This is because it only has a yes or no option on it.
Next up is the deleteAction
, copy the followin into the PostController
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public function deleteAction()
{
$id = $this->params()->fromRoute('id');
if (empty($id)) {
throw new \Exception('Id must be given; if given, it was not found.');
}
/** @var Post $post */
$post = $this->getEntityManager()->getRepository(Entity::POST)->find($id);
if (!$post instanceof Post) {
throw new \Exception('Something went wrong retreving this post, please try again or contact us.');
}
/** @var PostForm $form */
$form = $this->getServiceLocator()->get('post_delete_form');
/** @var Request $request */
$request = $this->getRequest();
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
if (array_key_exists('yes', $request->getPost()->toArray()['submit'])) {
//Save post to DB
$this->getEntityManager()->remove($post);
$this->getEntityManager()->flush();
//Redirect user to view all posts
$this->redirect()->toRoute('blog');
} else {
return $this->redirect()->toRoute('blog/view', [
'id' => $post->getId(),
'slug' => $post->getSlug(),
]);
}
}
}
// Bind object so existing values are set when viewing form
$form->bind($post);
return [
'form' => $form,
];
}
You’ll notice that it looks a lot like the editAction
. There are, however some subtle differences. For one, we use a
different $form
. Also, after the check we try to see if a key yes is present in the array of post data.
If it is, we don’t use the EntityManager
’s persist()
function to store the post, instead we user remove()
. This
tells the EntityManager
that it should be removed, however, until you flush()
it won’t actually be gone.
If the key yes
isn’t present, we route the user back to the post. If it is, and thus the post has been removed, we
route the user back to the index of the blog.
Also, we always bind the $post
object to the $form
object. This is opposed to the editAction
where we only want to
bind before a user sends us back data. For the deleteAction
we always want to show the stored data, so that we could
show the user the data that will be deleted if they were to proceed.
Next, we create the route to the page, the same was as for the edit, in the view.phtml
file with the code below (add
it below the edit link):
1
2
3
4
5
6
7
<a href="<?= $this->url('blog/view/delete', [
'id' => $this->escapeHtml($post->getId()),
'slug' => $this->escapeHtml($post->getSlug())
]) ?>"
title="<?= $this->translate('Delete') ?> - <?= $this->escapeHtml($post->getTitle()) ?>">
<?= $this->translate('Delete') ?>
</a>
If you were to view a post now, you would see the link appear. However, visiting it would get you a
ServiceNotFoundException
for your troubles.
We still have to create the PostDeleteForm.php
file and set up its factory in the Module.php
file of the module.
Create the PostDeleteForm.php
file next to the PostForm.php
and copy in the code below.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
namespace Blog\Form;
use Application\Form\AbstractForm;
use Zend\Form\Element;
class PostDeleteForm extends AbstractForm
{
public function __construct($name = 'post-delete-form', $options = [])
{
parent::__construct($name, $options);
$this->addElements();
}
public function addElements()
{
$this->add([
'name' => 'submit[yes]',
'type' => 'submit',
'attributes' => [
'name' => 'submit[yes]',
'value' => 'Delete post',
'data-action' => 'delete',
],
]);
$this->add([
'name' => 'submit[no]',
'type' => 'submit',
'attributes' => [
'name' => 'submit[no]',
'value' => 'Cancel',
'data-action' => 'cancel',
],
]);
}
}
As you can see, the start of this form is the same as for the PostForm
class, apart from the default name in the __
construct()
function.
You’ll notice that the form only contains two elements. Here a little piece of Zend magic happens. Zend recognises that
the names of the two elements are essentially the same, namely (sorry, couldn’t help myself): submit
. However,
the []
after it tells the Zend Framework to set it up as an array, allowing the elements to have the same name, but
different values.
Next up, we add the factory to the Module.php
file. Add the code below after the post_form
factory, but within the
array to be returned by the getServiceConfig()
function.
1
2
3
4
5
6
7
'post_delete_form' => function ()
{
$form = new PostDeleteForm();
$form->setInputFilter(new InputFilter());
return $form;
}
A quick note on this factory. You’ll notice that we use just “InputFilter”. We do not need to set anything special or
validate anything apart from the CSRF for this action. Therefore the default Zend InputFilter
class is enough.