Вихід ZF 1.8 порадував нас низкою нових, корисних компонентів. У цій статті я хочу розповісти про практику використання Zend_Navigation для побудови простого меню сайту, карти сайту і хлібних крихт. Особливо хочеться звернути увагу на використання Zend_Navigation в парі з Zend_Acl.
Показувати буду на прикладі пустої аплікухи, тому для початку створю каркас проекту використовуючи Zend_Tool.
$ zf create project ./ |
1. Меню
Насамперед, з допомогою ресурсів (теж з’явилися в ZF 1.8) налаштую Zend_View. Додаю в “application/configs/application.ini” наступний код :
; Views resources.view.encoding = "UTF-8" resources.view.basePath = APPLICATION_PATH "/views" resources.view.helperPath.Application_View_Helper = APPLICATION_PATH "/views/helpers" |
Далі у файлі “application/Bootstrap.php” створюю новий метод _initNavigation() (читайте комментарі в коді):
<?php class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { /* * Ініціалізуємо об'єкт навігатора і передаємо його в View * * @return Zend_Navigation */ public function _initNavigation() { // Ініціалізуємо View $this->bootstrapView(); $view = $this->getResource('view'); // Структура простого меню (можна винести в XML) $pages = array( array( 'controller' => 'index', 'label' => _('Головна сторінка'), ), array( 'controller' => 'users', 'action' => 'index', // Тут я обгортаю текст _(), щоб його можна було витягнути gettext'ом 'label' => _('Користувачі'), 'pages' => array ( array ( 'controller' => 'users', 'action' => 'new', 'label' => _('Додати користувача'), ), ) ), array ( 'controller' => 'users', 'action' => 'registration', 'label' => _('Реєстрація'), ), array ( 'controller' => 'users', 'action' => 'login', 'label' => _('Авторизація'), ), array ( 'controller' => 'users', 'action' => 'logout', 'label' => _('Вихід'), ) ); // Створюємо новий контейнер і передаємо йому структуру меню $container = new Zend_Navigation($pages); // Передаємо контейнер в View $view->menu = $container; return $container; } } ?> |
Нехай меню повинно відображатись на усіх сторінках сайту. Для цього ідеально підходить Zend_Layout.
$ mkdir application/layouts $ mkdir application/layouts/scripts $ touch application/layouts/scripts/default.phtml |
Додаю в шаблон “application/layouts/scripts/default.phtml” вивід меню і контенту сторінки:
<div id="menu"> <h3> <?php echo $this->translate('Меню'); ?>: </h3> <?php echo $this->navigation()->menu($this->menu); ?> </div> <div id="content"> <?php echo $this->layout()->content; ?> </div> |
А в “application/configs/application.ini” виношу налаштування для ресурсу layout, який ініціалізує Zend_Layout:
; Layout resources.layout.layout = "default" resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts" |
І запускаю:
Вуаля :). Бачимо готову, розгорнуту менюшку у якій активний пункт позначається як class=”active”.
2. Хлібні крихти
Ок, менюшка готова. Тепер я хочу, щоб при користуванні сайтом користувач завжди бачив де він є. Для цього гарно підходять, так звані “хлібні крихти”.
Для того, щоб аплікуха не матюкалась на відсутність контролера чи в’юшок я за допомогою Zend_Tool створюю контролер Users і додаю в нього необхідні дії та створюю в’юшки. Все дуже просто:
$ zf create controller users $ zf create action new --controller-name users $ zf create action registration --controller-name users $ zf create action login --controller-name users $ zf create action logout --controller-name users |
І плюс трохи нового коду в шаблоні layout’a (між меню і контентом):
<div id="breadcrumbs"> <h3> <?php echo $this->translate('Хлібні крихти'); ?>: </h3> <?php echo $this->navigation()->breadcrumbs($this->menu)->setLinkLast(true); ?> </div> |
Дивлюсь, що вийшло:
Класно :)?
Метод setLinkLast(true) означає, що останню крихту теж потрібно показувати лінком. Також можна вказувати роздільник і глибину – дивіться API
3. Sitemap
З сайтмапом теж все просто. Я вже не буду вдаватися в подбробиці. Все робиться по аналогії.
Ось мануал, а ось мінімальний код:
<?php echo $this->navigation()->sitemap($this->menu); ?> |
4. Zend_Navigation && Zend_Acl
А тепер я розповім про те, що мені сподобалося в Zend_Navigation найбільше. Це можливість використовувати його в парі з Zend_Acl!
Додам в Bootstrap ролі і привілеї для доступу до сторінок, а також ініціалізацію Zend_Acl. В результаті він виглядатиме ось так (знову ж таки читаємо коментарі):
<?php class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { /** * Ініціалізуємо ACL. * Створюємо ролі та ресурси. Роздаємо права доступу * * @return Zend_Acl */ protected function _initAcl() { $auth = Zend_Auth::getInstance(); // Визначаємо роль користувача. // Якщо він не авторизований, то значить "гість" $role = ($auth->hasIdentity() && !empty($auth->getIdentity()->role)) ? $auth->getIdentity()->role : 'guest'; $acl = new Zend_Acl(); // Створюємо ролі $acl->addRole(new Zend_Acl_Role('guest')) ->addRole(new Zend_Acl_Role('member'), 'guest') ->addRole(new Zend_Acl_Role('administrator'), 'member'); // Створюємо ресурси // Я використовую префікси в назвах ресурсів // "mvc:" - для сторінок $acl->add(new Zend_Acl_Resource('mvc:index')) ->add(new Zend_Acl_Resource('mvc:error')) ->add(new Zend_Acl_Resource('mvc:users')); // Пускаємо гостей на "морду" і на сторінку помилок $acl->allow('guest', array('mvc:error', 'mvc:index')); // А також на сторінку авторизації і реєстрації $acl->allow('guest', 'mvc:users', array('login', 'registration')); // Мемберам ж зась :) $acl->deny('member', 'mvc:users', array('login', 'registration')); // Ну і т.д. $acl->allow('member', 'mvc:users', array('index', 'logout')); $acl->allow('administrator', 'mvc:users', array('new')); // Чіпляємо ACL до Zend_Navigation Zend_View_Helper_Navigation_HelperAbstract::setDefaultAcl($acl); Zend_View_Helper_Navigation_HelperAbstract::setDefaultRole($role); return $acl; } /* * Ініціалізуємо об'єкт навігатора і передаємо його в View * * @return Zend_Navigation */ public function _initNavigation() { // Ініціалізуємо View $this->bootstrapView(); $view = $this->getResource('view'); // Структура простого меню (можна винести в XML) $pages = array( array( 'controller' => 'index', 'label' => _('Головна сторінка'), ), array( 'controller' => 'users', 'action' => 'index', // Ресурс для перевірки прав доступу 'resource' => 'mvc:users', // Привілей 'privilege' => 'index', // Тут я обгортаю текст _(), щоб його можна було витягнути gettext'ом 'label' => _('Користувачі'), 'pages' => array ( array ( 'controller' => 'users', 'action' => 'new', 'resource' => 'mvc:users', 'privilege' => 'new', 'label' => _('Додати користувача'), ), ) ), array ( 'controller' => 'users', 'action' => 'registration', 'resource' => 'mvc:users', 'privilege' => 'registration', 'label' => _('Реєстрація'), ), array ( 'controller' => 'users', 'action' => 'login', 'resource' => 'mvc:users', 'privilege' => 'login', 'label' => _('Авторизація'), ), array ( 'controller' => 'users', 'action' => 'logout', 'resource' => 'mvc:users', 'privilege' => 'logout', 'label' => _('Вихід'), ) ); // Створюємо новий контейнер і передаємо йому структуру меню $container = new Zend_Navigation($pages); // Передаємо контейнер в View $view->menu = $container; return $container; } } ?> |
Запускаю:
І бачу меню для гостей! А хлібні крихти пусті, тому що треба задати мінімальну глибину рівною нулю.
Підсумок
Взагалі Zend_Navigation дуже зручна і гнучка штука. А! Я ще забув сказати, що стандартні в’ю хелпери підтримують Zend_Translate – дуже зручно при створенні багатомовних сайтів.
Ніби все. Надіюсь ця стаття стане вам у пригоді. Зараз ще перекладу її на російську, щоб опублікувати на habrahabr.ru та zendframework.ru (дуже корисний ресурс!).
UPD. Тут Олександр Махомет підказує, що ось так робити
// Передаємо контейнер в View $view->menu = $container; |
не дуже зручно, бо можна забутися і затерти цю змінну в контролері.
Якщо на сайті тільки одне меню, то можна робити простіше:
$view->navigation($container); |
І виводити таким чином:
<?php echo $this->navigation()->menu(); ?> <?php echo $this->navigation()->breadcrumbs(); ?> |
Спасибі за цікаву статтю. Дуже радує, що українською.
Приходьте ще 😉
Спасибо, дружище!
Очень полезная статья, то что нужно!)
Дякую, також читав пів-року назад 🙂
Дякую, дуже корисна стаття
Будь-ласка 😉
привіт.. класна стаття.
А чи є helper, щоб я міг написати так:
в application.ini:
resources.router.routes.gallery-create.route = /gallery/create
resources.router.routes.gallery-create.defaults.module = default
resources.router.routes.gallery-create.defaults.controller = gallery
resources.router.routes.gallery-create.defaults.action = create
resources.router.routes.gallery-create.defaults.resource= mvc:admin
в bootstrap:
Zend_View_Helper_Routers_HelperAbstract::setDefaultAcl($acl);
Zend_View_Helper_Routers_HelperAbstract::setDefaultRole($role);