Zend Framework

Criando menu interativo com Zend Framework 2

Por em

Sobre o que é este tutorial

Neste tutorial mostrarei uma funcionalidade muito legal do Zend Framework 2: a possibilidade de criar um menu de usuário, sem se preocupar com HTML e de fácil manutenção.
Sabemos o quão importante é ter uma aplicação visual, ou seja, uma aplicação que agrade o usuário, que o cative visualmente. O Zend Framework 2 permite que você crie menus interativos e dinâmicos, tudo gerenciado no back-end. Portanto, se quisermos fazer alguma alteração nos itens de menus, as vezes nem mudaremos uma linha se quer do HTML que é gerado e isso é um ganho produtivo e tanto.

Qual é a ideia?

A ideia é usar o recurso Zend\Navigation do framework, é ele nos permite montar um menu estruturado. E, quando se instala o framework, por padrão já vem configurado o Twitter Bootstrap para o visual, então, montaremos um menu baseado na estrutura do Bootstrap. Nosso menu ficará assim:

Captura de tela 2015-03-21 14.09.26_mod

O que faremos?

  1. Instalar e configurar o esqueleto do Zend Framework 2 em nossa máquina.
  2. Registrar o menu nas configurações globais do Zend Framework 2 e configurar o Navigation.
  3. Integrar o layout padrão com o menu registrado.
  4. Testar o que fizemos. 

Passos

  1. Instalar o esqueleto do Zend Framework 2 em nossa máquina (instalaremos via git).

Veja como instalar o Zend Framework 2

  1. Registrar o menu nas configurações globais do Zend Framework 2 e configurar o Navigation.

Faremos um menu simples com alguns itens de sub-menu. Criaremos um menu Clientes e Produtos e sub-menus para novo cadastro e listagem.

Irei criar um módulo exemplo Exemplo com um Controller para cuidar dos clientes e um para os produtos. Usarei o zftool para criar o módulo Exemplo.

php zf.php create module Exemplo

Este comando criará um módulo Exemplo. Agora precisamos configurar, os controllers, as rotas e as views que precisamos:

./module/Exemplo/src/Exemplo/Controller/ClienteController
<?php

namespace Exemplo\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class ClienteController extends AbstractActionController
{
    public function indexAction()
    {
        return new ViewModel();
    }

    public function newAction()
    {
        return new ViewModel();
    }

    public function listAction()
    {
        return new ViewModel();
    }
}
./module/Exemplo/view/exemplo/cliente/new.phtml
<h3>Cadastro de Cliente</h3>
./module/Exemplo/view/exemplo/cliente/list.phtml
<h3>Listagem de Cliente</h3>
./module/Exemplo/src/Exemplo/Controller/ProdutoController
<?php

namespace Exemplo\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class ProdutoController extends AbstractActionController
{
    public function indexAction()
    {
        return new ViewModel();
    }

    public function newAction()
    {
        return new ViewModel();
    }

    public function listAction()
    {
        return new ViewModel();
    }
}
./module/Exemplo/view/exemplo/produto/new.phtml
<h3>Cadastro de Produto</h3>

./module/Exemplo/view/exemplo/produto/list.phtml
<h3>Listagem de Produto</h3>
./module/Exemplo/config/module.config.php
<?php
return [
    'controllers' => [
        'invokables' => [
            'Exemplo\Controller\ClienteController' => 'Exemplo\Controller\ClienteController',
            'Exemplo\Controller\ProdutoController' => 'Exemplo\Controller\ProdutoController',
        ]
    ],
    'router' => array(
        'routes' => array(
            'cliente' => array(
                'type' => 'Literal',
                'options' => array(
                    'route'    => '/cliente',
                    'defaults' => array(
                        'controller' => 'Exemplo\Controller\ClienteController',
                        'action'     => 'index',
                    ),
                ),
                'may_terminate' => true,
                'child_routes' => array(
                    'new' => array(
                        'type'    => 'Literal',
                        'options' => array(
                            'route'    => '/new',
                            'defaults' => array(
                                'action' => 'new'
                            ),
                        ),
                    ),
                    'list' => array(
                        'type'    => 'Literal',
                        'options' => array(
                            'route'    => '/list',
                            'defaults' => array(
                                'action' => 'list'
                            ),
                        ),
                    ),
                ),
            ),
            'produto' => array(
                'type' => 'Literal',
                'options' => array(
                    'route'    => '/produto',
                    'defaults' => array(
                        'controller' => 'Exemplo\Controller\ProdutoController',
                        'action'     => 'index',
                    ),
                ),
                'may_terminate' => true,
                'child_routes' => array(
                    'new' => array(
                        'type'    => 'Literal',
                        'options' => array(
                            'route'    => '/new',
                            'defaults' => array(
                                'action' => 'new'
                            ),
                        ),
                    ),
                    'list' => array(
                        'type'    => 'Literal',
                        'options' => array(
                            'route'    => '/list',
                            'defaults' => array(
                                'action' => 'list'
                            ),
                        ),
                    ),
                ),
            ),
        ),
    ),
    'view_manager' => [
        'template_path_stack' => [
            __DIR__ . '/../view',
        ],
    ],
];

Agora com arquivos necessários configurados, precisamos entender algumas considerações sobre o Zend Navigation.

Ele não vem configurado por padrão no Zend Framework 2, precisamos registra-lo nos serviços da aplicação e configurar um menu padrão com nome default,

senão a aplicação lançará um erro.

O Navigation pode renderizar qualquer tipo de menu: Bootstrap, Foundation, JQuery UI, etc. Mas, temos que fazer um template específico usando a implementação de um AbstractPage, que armazena informações necessárias para montar o menu com o HTML que queremos. Veremos isto um pouco mais abaixo.

Agora vamos registrar o menu com clientes e produtos nas configurações globais da aplicação que ficam em config/autoload/global.php:

<?php

return [
    'navigation' => [
        'default' => [
            [
                'label' => 'Clientes',
                'route' => 'cliente',
                'pages' => [
                    [
                        'label' => 'Listar',
                        'route' => 'cliente/list',
                        'action' => 'list',
                    ],
                    [
                        'label' => 'Novo',
                        'route' => 'cliente/new',
                        'action' => 'new',
                    ],
                ]
            ],
            [
                'label' => 'Produtos',
                'route' => 'produto',
                'pages' => [
                    [
                        'label' => 'Listar',
                        'route' => 'produto/list',
                        'action' => 'list',
                    ],
                    [
                        'label' => 'Novo',
                        'route' => 'produto/new',
                        'action' => 'new',
                    ],
                ]
            ],
        ]
    ],
];

Venham que registrei o menu dentro da key navigation e registrei o nome de default que é o menu padrão. Senão registrado um menu com key default, o Navigation lançará um erro posteriormente.

O menu é simples, uma coleção de arrays, sendo a key label o nome do menu que aparecerá na página, a key route, a rota configurada no module.config.php dos módulos (se a rota não for configurada corretamente ou não existir a aplicação lançará um erro), a key action se quisermos utilizar uma action específica do controller (neste caso não a usaremos, porque o menu só terá ação nos sub-itens internos) e a key pages para especificar uma coleção de sub-itens com keys iguais as que mencionei agora: label, route, pages e action.

Agora temos que registrar o serviço do Navigation, adicionando isto na key service_manager no module.config.php do módulo Application:

'factories' =>[
    'Navigation' => 'Zend\Navigation\Service\DefaultNavigationFactory',
]
  1. Integrar o layout padrão com o menu registrado

Criarei o menu no layout da aplicação que fica em ./module/Application/view/layout/layout.phtml. Nos chamaremos o view helper do Navigation e indicaremos um template específico

para montar o menu com base na estrutura do Bootstrap.

O template para gerar o menu Bootstrap pode ser encontrado aqui. É aqui que você poderá fazer que o quiser para renderizar o menu HTML. Coloque o navigation.phtml junto com o layout.phtml.

Agora é só chamarmos o menu no layout.phtml e renderiza-lo. Substitua:

<li class="active"><a href="<?php echo $this->url('home') ?>"><?php echo $this->translate('Home') ?></a></li>

Por:

<?php $partial = ['layout/navigation.phtml', 'default']; ?>
<?php $this->navigation('navigation')->menu()->setPartial($partial); ?>
<?php echo $this->navigation('navigation')->menu()->render(); ?>

Na primeira linha armazenamos o caminho para nosso template e o nome do menu que registramos, na segunda linha chamamos o view helper do Navigation, e informamos a ele

que queremos montar um menu com o template específico que queremos e na terceira renderizamos o menu.

  1. Testar o que fizemos

Para testar o que fizemos usaremos o php built-in-server para executar a aplicação no nosso browser. Faça em seu terminal:

php -S localhost:9999 -t public public/index.php

Agora é só abrir seu browser e digitar localhost:9999. Se aparecer uma página mostrando o Zend Framework 2, então tudo deu certo. Agora só testar o funcionamento do menu.

Se você quiser ver o código deste tutorial acesse http://github.com/codeedu/menu-bootstrap.git

É isso aí pessoal, espero que tenham gostado. Vejam que não é complicado montar um menu com Bootstrap e que o Zend Framework 2 traz recursos poderosos

para dar um UP no visual do nossa aplicação, porque, se quisermos mudar os itens do menu da aplicação, basta que mudemos as configurações no global.php sem

mexer com uma linha de HTML, o que é incrível por todas as razões de estrutura da aplicação e de futuras manutenções.

Referências:

http://framework.zend.com/manual/current/en/modules/zend.navigation.intro.html

http://framework.zend.com/manual/current/en/modules/zend.navigation.quick-start.html

http://framework.zend.com/manual/current/en/modules/zend.navigation.pages.html

http://framework.zend.com/manual/current/en/modules/zend.navigation.containers.html