В прошлый раз мы рассмотрели создание своих контроллеров и действий. Теперь настало время написать свое мини-приложение с
CRUD (create-read-update-delete) функционалом. Так как вопросы работы с базой данных я оставлю на следующий раз, то работать мы будем с сессиями. Раз уж мы
создали контроллер BookController, давайте продолжим и напишем мини-каталог книг.
У каждой книги будет свое название, автор и краткое описание.
Для создания книги нам понадобится форма. Воспользуемся компонентом Zend_Framework для работы с формами, который носит незамысловатое название Zend_Form.
В папке application создадим каталог forms. Добавим класс Form_Book, экземпляры которого будут наследовать все свойства компонента Zend_Form, в файл Book.php:
class Form_Book extends Zend_Form
{
public function init()
{
// name element
$name = $this->createElement('text', 'name');
$name->setLabel("Enter book's name:");
$name->setRequired(true);
$name->setAttrib('size', 40);
$this->addElement($name);
// author element
$author = $this->createElement('text', 'author');
$author->setLabel("Enter book's author:");
$author->setRequired(true);
$author->setAttrib('size', 40);
$this->addElement($author);
// description element
$description = $this->createElement('textarea', 'description');
$description->setLabel("Short description:");
$description->setRequired(true);
$description->setAttrib('cols', 50);
$description->setAttrib('rows', 4);
$this->addElement($description);
// submit button
$this->addElement('submit', 'submit', array('label' => 'Submit'));
}
}
Мы добавили два текстовых поля, одну область и кнопку, также мы указали, что все поля являются обязательными для заполнения.
В загрузчик Bootstrap.php добавим метод _initAutoload:
protected function initAutoload()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$resourceLoader = new Zend_Loader_Autoloader_Resource(array( 'basePath' => APPLICATION_PATH, 'namespace' => '', 'resourceTypes' => array( 'form' => array( 'path' => 'forms/', 'namespace' => 'Form'
)
)
));
return $autoloader;
}
Теперь Zend_Framework знает, где искать наши формы. В файле BookController.php добавим действие createAction:
public function createAction()
{
$frmBook = new Form_Book();
$frmBook->setMethod('post');
$this->view->form = $frmBook;
}
В папке views/scripts/book создадим представление для действия create. Добавим файл create.phtml:
<div id="_mcePaste"><h2>Create New Book</h2></div>
<div id="_mcePaste"><?php echo $this->form;?></div>
Как видите, чтобы отобразить форму надо всего лишь написать
$this->form
. Просто, не правда ли?
Перейдя по ссылке http://zf/book/create, вы увидите нашу форму. Теперь нам нужно инициализировать объект сессии, который будет выступать
хранилищем книг, мы будем заносить очередную книгу в сессию после обработки пост запроса формы. Добавим метод preDispatch в BookController.
Метод preDispatch() в контроллере выполняется до любого действия. В нашем случае очень удобно инициализировать сессию в этом методе, что мы и сделаем. Для работы с сессиями будем использовать компонент Zend_Framework, который называется Zend_Session. Нам понадобится класс Zend_Session_Namespace.
/**
* session variable
*
* @var Zend_Session_Namespace
*/
protected $session;
public function preDispatch()
{
$this->session = new Zend_Session_Namespace('default');
if(!$this->session->books) {
$this->session->books = array();
$this->session->currentItemId = 0;
}
}
Для явной идентификации книги в нашем каталоге мы будем использовать счетчик currentItemId, который также будет храниться в сессии.
Теперь осталось сохранить информацию в сессии после добавления новой книги. Отредактируем метод createAction в классе BookController:
public function createAction()
{
$frmBook = new Form_Book();
$frmBook->setMethod('post');
if ($this->_request->isPost()) {
if ($frmBook->isValid($this->_request->getPost())) {
$this->session->currentItemId++;
$book = new stdClass();
$book->id = $this->session->currentItemId;
$book->name = $frmBook->getValue('name');
$book->author = $frmBook->getValue('author');
$book->description = $frmBook->getValue('description');
$this->session->books[$this->session->currentItemId] = $book;
$this->_redirect('/book');
}
}
$this->view->form = $frmBook;
}
А в indexAction добавим переменную, указывающую на список добавленных книг:
public function indexAction()
{
$this->view->books = $this->session->books;
}
В файле views/scripts/book/index.phtml выведем список имеющихся книг:
<h2>List of all books</h2>
<?php
if (count($this->books)) {
?>
<dl>
<?php
foreach ($this->books as $book) {
if (!$book instanceof stdClass) {
continue;
}
?>
<dt>
<?= $book->name ?> | <small>author: <?= $book->author ?></small> |
<a href="/book/update/id/<?= $book->id ?>">update</a>
<a href="/book/delete/id/<?= $book->id ?>">delete</a>
</dt>
<dd>
<?= $book->description ?>
</dd>
<?php
}
?>
</dl>
<?php
}
Теперь у нас есть список книг! Можно создавать новые книги, и они будут добавляться в этот список. Осталось реализовать возможность редактирования и удаления книги из списка. Займемся сначала редактированием. В классе BookController добавим действие updateAction:
public function updateAction()
{
if ($this->getRequest()->getParam('id')) {
$id = $this->getRequest()->getParam('id');
$frmBook = new Form_Book();
if (isset($this->session->books[$id])) {
$book = $this->session->books[$id];
$frmBook->populate(array(
'name' => $book->name,
'author' => $book->author,
'description' => $book->description
)
);
} else {
throw new Zend_Exception('Update failed: book not found!');
}
$this->view->form = $frmBook;
}
}
Добавим скрипт представления views/scripts/book/update.phtml:
<h2>Update Book</h2>
<?=$this->form?>
Перейдя по ссылке http://zf/book/update/id/1, можно увидеть содержимое выбранного элемента. Теперь напишем несколько строк для сохранения введенной информации.
public function updateAction()
{
if ($this->getRequest()->getParam('id')) {
$id = $this->getRequest()->getParam('id');
$frmBook = new Form_Book();
if (isset($this->session->books[$id])) {
if ($this->getRequest()->isPost()) {
if ($frmBook->isValid($this->_request->getPost())) {
$book = new stdClass();
$book->id = $id;
$book->name = $frmBook->getValue('name');
$book->author = $frmBook->getValue('author');
$book->description = $frmBook->getValue('description');
$this->session->books[$id] = $book;
$this->_redirect('/book');
}
} else {
$book = $this->session->books[$id];
$frmBook->populate(array(
'name' => $book->name,
'author' => $book->author,
'description' => $book->description
)
);
}
} else {
throw new Zend_Exception('Update failed: book not found!');
}
$this->view->form = $frmBook;
}
}
Мы снова проверяем, был ли выполнен пост запрос. Если это так, то получаем данные из формы, ищем книгу в массиве и сохраняем, используя уникальный номер книги. Осталось добавить лишь один метод для удаления книги из каталога. Это действие будет чрезвычайно простое. Добавляем deleteAction в контроллер BookController:
public function deleteAction()
{
if ($this->getRequest()->getParam('id')) {
if (isset($this->session->books[$this->getRequest()->getParam('id')])) {
unset($this->session->books[$this->getRequest()->getParam('id')]);
$this->_redirect('/book');
} else {
throw new Zend_Exception('Delete failed: book not found!');
}
}
}
Мы проверяем есть ли книга в каталоге, если есть – то удаляем элемент из нашего массива. Вот и все! Мы создали небольшое приложение, которое позволяет добавлять, редактировать и удалять элементы. Познакомились с сессиями. В следующий раз я покажу как на примере одной из библиотек строить ajax-приложения ^_^
P.S. Закончен перевод 4-й и 6-й глав документации Zend Framework. Zend Autoloading и Zend Layout теперь доступны на русском языке.
Да, было бы смешно, если б не было так грустно …
Благодарю за такую занимательную точку зрения. Я с ней не совсем согласен, но она имеет право быть.
[…] вспомним наш каталог книг, который мы делали при помощи компонента Zend_Session_Namespace. […]