### 使列表更有用
**修改列表模板**
> module/Blog/view/blog/list/index.phtml
~~~
<h1>Blog Posts</h1>
<div class="list-group">
<?php foreach ($this->posts as $post): ?>
<div class="list-group-item">
<h4 class="list-group-item-heading">
<a href="<?= $this->url('blog/detail', ['id' => $post->getId()]) ?>">
<?= $post->getTitle() ?>
</a>
</h4>
<div class="btn-group" role="group" aria-label="Post actions">
<a class="btn btn-xs btn-default" href="<?= $this->url('blog/edit', ['id' => $post->getId()]) ?>">Edit</a>
<a class="btn btn-xs btn-danger" href="<?= $this->url('blog/delete', ['id' => $post->getId()]) ?>">Delete</a>
</div>
</div>
<?php endforeach ?>
</div>
<div class="btn-group" role="group" aria-label="Post actions">
<a class="btn btn-primary" href="<?= $this->url('blog/add') ?>">Write new post</a>
</div>
~~~
**模块配置路由**
编辑和删除
> module/Blog/config/module.config.php
~~~
use Zend\Router\Http\Segment;
return [
'service_manager' => [ /* ... */ ],
'controllers' => [ /* ... */ ],
'router' => [
'routes' => [
'blog' => [
/* ... */
'child_routes' => [
/* ... */
// 编辑
'edit' => [
'type' => Segment::class,
'options' => [
'route' => '/edit/:id',
'defaults' => [
'controller' => Controller\WriteController::class,
'action' => 'edit',
],
'constraints' => [
'id' => '[1-9]\d*',
],
],
],
// 删除
'delete' => [
'type' => Segment::class,
'options' => [
'route' => '/delete/:id',
'defaults' => [
'controller' => Controller\DeleteController::class,
'action' => 'delete',
],
'constraints' => [
'id' => '[1-9]\d*',
],
],
],
],
],
],
],
'view_manager' => [ /* ... */ ],
];
~~~
### 将对象绑定到表单
**控制器工厂类**
> module/Blog/src/Factory/WriteControllerFactory.php
~~~
use Blog\Model\PostRepositoryInterface;
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
$formManager = $container->get('FormElementManager');
return new WriteController(
$container->get(PostCommandInterface::class),
$formManager->get(PostForm::class),
$container->get(PostRepositoryInterface::class)
);
}
~~~
**修改控制器**
添加编辑动作
> module/Blog/src/Controller/WriteController.php
~~~
<?php
namespace Blog\Controller;
use Blog\Form\PostForm;
use Blog\Model\Post;
use Blog\Model\PostCommandInterface;
use Blog\Model\PostRepositoryInterface;
use InvalidArgumentException;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class WriteController extends AbstractActionController
{
/**
* @var PostCommandInterface
*/
private $command;
/**
* @var PostForm
*/
private $form;
/**
* @var PostRepositoryInterface
*/
private $repository;
/**
* @param PostCommandInterface $command
* @param PostForm $form
* @param PostRepositoryInterface $repository
*/
public function __construct(
PostCommandInterface $command,
PostForm $form,
PostRepositoryInterface $repository
) {
$this->command = $command;
$this->form = $form;
$this->repository = $repository;
}
public function addAction()
{
$request = $this->getRequest();
$viewModel = new ViewModel(['form' => $this->form]);
if (! $request->isPost()) {
return $viewModel;
}
$this->form->setData($request->getPost());
if (! $this->form->isValid()) {
return $viewModel;
}
$post = $this->form->getData();
try {
$post = $this->command->insertPost($post);
} catch (\Exception $ex) {
// An exception occurred; we may want to log this later and/or
// report it to the user. For now, we'll just re-throw.
throw $ex;
}
return $this->redirect()->toRoute(
'blog/detail',
['id' => $post->getId()]
);
}
// 添加编辑动作
public function editAction()
{
$id = $this->params()->fromRoute('id');
if (! $id) {
return $this->redirect()->toRoute('blog');
}
try {
$post = $this->repository->findPost($id);
} catch (InvalidArgumentException $ex) {
return $this->redirect()->toRoute('blog');
}
$this->form->bind($post);
$viewModel = new ViewModel(['form' => $this->form]);
$request = $this->getRequest();
if (! $request->isPost()) {
return $viewModel;
}
$this->form->setData($request->getPost());
if (! $this->form->isValid()) {
return $viewModel;
}
$post = $this->command->updatePost($post);
return $this->redirect()->toRoute(
'blog/detail',
['id' => $post->getId()]
);
}
}
~~~
### 创建编辑模板
**创建通用表单模板**
> module/Blog/view/blog/write/form.phtml
~~~
<?php
$form = $this->form;
$fieldset = $form->get('post');
$title = $fieldset->get('title');
$title->setAttribute('class', 'form-control');
$title->setAttribute('placeholder', 'Post title');
$text = $fieldset->get('text');
$text->setAttribute('class', 'form-control');
$text->setAttribute('placeholder', 'Post content');
$submit = $form->get('submit');
$submit->setValue($this->submitLabel);
$submit->setAttribute('class', 'btn btn-primary');
$form->prepare();
echo $this->form()->openTag($form);
?>
<fieldset>
<div class="form-group">
<?= $this->formLabel($title) ?>
<?= $this->formElement($title) ?>
<?= $this->formElementErrors()->render($title, ['class' => 'help-block']) ?>
</div>
<div class="form-group">
<?= $this->formLabel($text) ?>
<?= $this->formElement($text) ?>
<?= $this->formElementErrors()->render($text, ['class' => 'help-block']) ?>
</div>
</fieldset>
<?php
echo $this->formSubmit($submit);
echo $this->formHidden($fieldset->get('id'));
echo $this->form()->closeTag();
~~~
**修改添加帖子模板**
> module/Blog/view/blog/write/add.phtml
~~~
<h1>Add a blog post</h1>
<?php
$form = $this->form;
$form->setAttribute('action', $this->url());
echo $this->partial('blog/write/form', [
'form' => $form,
'submitLabel' => 'Insert new post',
]);
~~~
**创建编辑帖子模板**
> module/Blog/view/blog/write/edit.phtml
~~~
<h1>Edit blog post</h1>
<?php
$form = $this->form;
$form->setAttribute('action', $this->url('blog/edit', [], true));
echo $this->partial('blog/write/form', [
'form' => $form,
'submitLabel' => 'Update post',
]);
~~~
### 添加更新功能
**数据库操作命令类**
> module/Blog/src/Model/ZendDbSqlCommand.php
~~~
public function updatePost(Post $post)
{
if (! $post->getId()) {
throw new RuntimeException('Cannot update post; missing identifier');
}
$update = new Update('posts');
$update->set([
'title' => $post->getTitle(),
'text' => $post->getText(),
]);
$update->where(['id = ?' => $post->getId()]);
$sql = new Sql($this->db);
$statement = $sql->prepareStatementForSqlObject($update);
$result = $statement->execute();
if (! $result instanceof ResultInterface) {
throw new RuntimeException(
'Database error occurred during blog post update operation'
);
}
return $post;
}
~~~
### 实现删除功能
**数据库操作命令类**
> module/Blog/src/Model/ZendDbSqlCommand.php
~~~
public function deletePost(Post $post)
{
if (! $post->getId()) {
throw new RuntimeException('Cannot update post; missing identifier');
}
$delete = new Delete('posts');
$delete->where(['id = ?' => $post->getId()]);
$sql = new Sql($this->db);
$statement = $sql->prepareStatementForSqlObject($delete);
$result = $statement->execute();
if (! $result instanceof ResultInterface) {
return false;
}
return true;
}
~~~
**创建删除博文控制器**
> module/Blog/src/Controller/DeleteController.php
~~~
<?php
namespace Blog\Controller;
use Blog\Model\Post;
use Blog\Model\PostCommandInterface;
use Blog\Model\PostRepositoryInterface;
use InvalidArgumentException;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class DeleteController extends AbstractActionController
{
/**
* @var PostCommandInterface
*/
private $command;
/**
* @var PostRepositoryInterface
*/
private $repository;
/**
* @param PostCommandInterface $command
* @param PostRepositoryInterface $repository
*/
public function __construct(
PostCommandInterface $command,
PostRepositoryInterface $repository
) {
$this->command = $command;
$this->repository = $repository;
}
public function deleteAction()
{
$id = $this->params()->fromRoute('id');
if (! $id) {
return $this->redirect()->toRoute('blog');
}
try {
$post = $this->repository->findPost($id);
} catch (InvalidArgumentException $ex) {
return $this->redirect()->toRoute('blog');
}
$request = $this->getRequest();
if (! $request->isPost()) {
return new ViewModel(['post' => $post]);
}
if ($id != $request->getPost('id')
|| 'Delete' !== $request->getPost('confirm', 'no')
) {
return $this->redirect()->toRoute('blog');
}
$post = $this->command->deletePost($post);
return $this->redirect()->toRoute('blog');
}
}
~~~
**控制器工厂类**
> module/Blog/src/Factory/DeleteControllerFactory.php
~~~
<?php
namespace Blog\Factory;
use Blog\Controller\DeleteController;
use Blog\Model\PostCommandInterface;
use Blog\Model\PostRepositoryInterface;
use Interop\Container\ContainerInterface;
use Zend\ServiceManager\Factory\FactoryInterface;
class DeleteControllerFactory implements FactoryInterface
{
/**
* @param ContainerInterface $container
* @param string $requestedName
* @param null|array $options
* @return DeleteController
*/
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new DeleteController(
$container->get(PostCommandInterface::class),
$container->get(PostRepositoryInterface::class)
);
}
}
~~~
**模块配置**
> module/Blog/config/module.config.php
控制器工厂地图
~~~
'controllers' => [
'factories' => [
Controller\ListController::class => Factory\ListControllerFactory::class,
Controller\WriteController::class => Factory\WriteControllerFactory::class,
// Add the following line:
Controller\DeleteController::class => Factory\DeleteControllerFactory::class,
],
],
~~~
添加删除帖子路由
~~~
'router' => [
'routes' => [
'blog' => [
/* ... */
'child_routes' => [
/* ... */
'delete' => [
'type' => Segment::class,
'options' => [
'route' => '/delete/:id',
'defaults' => [
'controller' => Controller\DeleteController::class,
'action' => 'delete',
],
'constraints' => [
'id' => '[1-9]\d*',
],
],
],
],
],
],
],
~~~
**创建删除页面模板**
> module/Blog/view/blog/delete/delete.phtml
~~~
<h1>Delete post</h1>
<p>Are you sure you want to delete the following post?</p>
<ul class="list-group">
<li class="list-group-item"><?= $this->escapeHtml($this->post->getTitle()) ?></li>
</ul>
<form action="<?php $this->url('blog/delete', [], true) ?>" method="post">
<input type="hidden" name="id" value="<?= $this->escapeHtmlAttr($this->post->getId()) ?>" />
<input class="btn btn-default" type="submit" name="confirm" value="Cancel" />
<input class="btn btn-danger" type="submit" name="confirm" value="Delete" />
</form>
~~~