В прошлый раз мы рассмотрели создание своих контроллеров и действий. Теперь настало время написать свое мини-приложение с
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>&nbsp;
                <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 теперь доступны на русском языке.

Leave a Reply

3 thoughts on “Каталог книг на основе сессий”
  1. Да, было бы смешно, если б не было так грустно …

  2. Благодарю за такую занимательную точку зрения. Я с ней не совсем согласен, но она имеет право быть.

Leave a Reply

Your email address will not be published. Required fields are marked *