domingo, 18 de agosto de 2013

Novas biritas : Introdução ao Zend Framework 2 - Parte 3 - 1 - Rotas, links e menus

Chegamos agora ao ponto onde você criou centenas de 'controllers' e outras dezenas de 'actions', e então faz-se necessário colocar tudo isso em menus ou links por ai.
Para conseguir organizar essa fauna de conteudos, o zf2 disponibiliza as 'routes' ( rotas em inglês, para quem não sabe ).
As 'routes' servem para fazer um mapeamento ou busca nas urls o caminho do conteudo desejado.

Para fazer uma rota, você precisa editar o arquivo do seu módulo 'module/Meumodulo/config/module.config.php' .

Dentro desse arquivo, você encontrara o array
return array(
    ...
    'router' =>array(
          'routes' => array(
                     ...
          ),
    ),
    ...
);

A variável 'router' é a variável que define o roteamento das páginas. Um modo de ficar mais simples de organizar esse array ( que pode ficar enorme conforme vai acrescentando coisas ),  é separar o array do router assim:

// Você declara e preenche a variável '$router' antes do 'return'
$router = array(
          'routes' => array(
                     ...
          ),
);

// E aqui o array de configuração do módulo
return array(
    ...
    'router' => $router,
    ...
);

Bom, sabendo da localização, vamos ver como usar isso. Primeiro temos de criar uma rota, que consiste na seguinte forma

$minharota= array(          
    'type' => 'Zend\Mvc\Router\Http\Literal',
    'options' => array(
        'route' => '/endereco/de/minha/rota',
        'defaults' => array(
            'controller' => 'Meumodulo\Controller\Meucontroller',
            'action'     => 'minhaaction',
        ),
    ),
);

Explicando:

type : define o tipo da rota. Aqui é o tipo 'Literal', que nada mais é que dizer explicitamente qual o módulo, controller e action do conteúdo.

route : esse é um alias, um endereço qualquer que você mesmo escolhe que deve ser digitado na url para acessar o conteúdo. Se você quiser que o conteúdo do action 'index' do controller 'index' do modulo 'application' apareça na url '/texto' ou '/esta/e/uma/url/estupidamente/grande' ,  basta colocar na variável route e digitar na url esses endereços bizarros que vai aparecer o conteúdo de '/application/index/index/'

defaults : aqui é definido o endereço REAL do conteúdo que deve ser acessado. Nas rotas literais, esse é o único endereço da rota, nas rotas do tipo 'segment' esse é um valor a ser chamado por padrão, isso será explicado daqui a pouco.

controller e action : bom, está claro o que são esses valores. Com ênfase na parte do controller, onde você precisa definir o módulo da qual o controller pertence.


Bom, assim que você cria sua rota, você adiciona aos 'routes'

$router = array(
    'routes' => array(
        'minharota1' => $minharota1,
        'minharota2' => $minharota2,
        ...
    ),
);

O nome 'minharota1' e a variável '$minharota1' e seguinte, não precisam ter o mesmo nome. Isso é uma padrão que eu adotei para facilitar a organização da configuração e melhor explicar nesse tutorial como funciona a coisa.
Na verdade você pode evitar essas variáveis e jogar como arrays puros diretamente na varável 'router' da configuração.

Uma coisa imprescindível é definir uma rota literal para sua página inicial do aplicativo.  Sim, bom do zendo que não precisa ser necessariamente o 'application\index\index' o endereço inicial, você pode definir uma route para a página inicial. No geral ela vem assim

$home = array(
    'type' => 'Zend\Mvc\Router\Http\Literal',
    'options' => array(
        'route' => '/',
        'defaults' => array(
            'controller' => 'Application\Controller\Index',
            'action'     => 'index',
        ),
    ),
),

e o que define a página inicial não é o nome 'home', mas sim a variável 'route' ser definida como '/' - o diretório raiz onde teremos

$router = array(
    'routes' => array(
        'home' => $home,
        'minharota1' => $minharota1,
        'minharota2' => $minharota2,
        ...
    ),
);

Agora, uma vez criadas as rotas e colocadas no config certo, você pode digitar os endereços definidos nas variáveis 'routes' para testar.

O tipo de rota literal é a mais simples, e boa para sites simples. Para sites um nível a mais de complexidade, os endereços são mais dinâmicos e envolve variáveis. Para isso existe a rota do tipo 'Segment'. 

O tipo 'Segment' segue a seguinte estrutura

$minharotasegment= array(          
    'type' => 'Zend\Mvc\Router\Http\Segment',
    'options' => array(
        'route' => '/algum/endereco[/:var]',
        'constraints' => array(
            'var' => '[a-zA-Z0-9_-]*', // Define o regexp de busca desejado
        ),
        'defaults' => array(
            'controller'    => 'Meumodule\Controller\Meucontroller',
            'action'        => 'meuaction',
            'var' => '123abc',
        ),
    ),
);

Aqui como podemos ver, temos uma mudança na variável 'route'. o termo '[:var]' define uma variável a ser digitada na url e tratada pelo zend no action 'meuaction' do controller 'Meucontroller' definido na variavel 'defaults'. Ainda em 'defaults', definimos um valor padrão para 'var' caso esse não tenha sido fornecido na url. Caso não precise de um valor padrão, basta apagar do 'defaults'.

Agora, para pegar o valor de 'var' da url, basta usar no controller definido no 'defaults' o helper

$var = $this->params('var');

Podemos definir varias variáveis no route

'route' => '/algum/endereco[/:var1[/:var2[/:var3]]]',

e basta declará-las em 'constraints' juntamente com o pattern desejado e no 'defaults' os valores padrões.

Ainda podemos fazer um mix de rota com variáveis

'route' => '/trecho1[/:var1[/trecho2[/:var2[/trecho3[/:var3]]]]]', 

e qualquer outra combinação que lhe venha a cabeça.
Para entender o essa route, só ver que tudo que estiver entre colchetes '[ ]' é considerado opcional, e tudo que vier depois do dois pontos ':' é o nome da variável. Portanto, não escreva nada atrás do nome da variável que não seja o colchete de fechamento ']'.

Também podemos ( e na maioria das vezes vamos ) usar variáveis pré-definidas no zend. Duas delas são o ':controller' e o ':action'. Numa rota seriam usados assim:

$minharotasegment=array(
    'type'    => 'Zend\Mvc\Router\Http\Segment',
    'options' => array(
        'route'    => '/endereco/segment/[:controller[/:action]]',
        'constraints' => array(
            'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
            'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',
       	),
	'defaults' => array(
            'controller' => 'Meucontroller',
            'action'     => 'meuaction', 
        ),
    ),
);

onde vemos que podemos definir variáveis que chamem por um controller ou por um action na rota definida. Na verdade é isso que é feito por padrão no SkelettonApplication do Zend, ele define a rota da raiz '/[:controller[/:action]]' onde a sequência digitada é o controller e o action, como sempre foi no zend, apenas que agora as rotas dão liberdade para você definir o caminho como você precisar com mais poder. Não que não desse para fazer isso no ZF1, mas que enquanto no ZF1 isso era apenas uma regalia, agora no ZF2 é rotineiro.

Entremos na última parte sobre rotas nesse tutorial, as subrrotas. As subrotas são parecidas com as rotas segment, mas na verdade você pode considerá-las como um 'subconjunto' de uma rota pai que é segment ou literal. Uma subrota é definida assim:
$minhasubrrota=array(
    'type'    => 'Zend\Mvc\Router\Http\Literal',
    'options' => array(
        'route'    => '/endereco/da/subrrota',
        'constraints' => array(
            'controller' => 'Meumodulodasubrrota\Controller\Meucontrollerdasubrrota',
            'action'     => 'meuactiondasubrota',
       	),
    ),
);

enfim, você na verdade cria uma rota como qualquer outra, com a diferença que ela vai ser colocada aqui:

$minharota=array(
    'type' => 'Zend\Mvc\Router\Http\Literal',
    'options' => array(
        'route'    => '/application',
        'defaults' => array(
            '__NAMESPACE__' => 'Application\Controller',
            'controller'    => 'Index',
            'action'        => 'index',
        ),
    ),
    'may_terminate' => true,
    'child_routes' => array(
        'minhasubrota' => $minhasubrrota,
    ),
);

Como funciona isso ? Você simplesmente vai digitar na url '/endereco/da/rota' que vai aparecer o conteudo do controller e action no default, mas se voce digitar '/endereco/da/rota/endereco/da/surrota' vai aparecer o conteudo definido no controller e action do default da subrrota. A vantagem disso é que você pode colocar muitas subrrotas sob uma mesma rota:

$minharota=array(
    'type' => 'Zend\Mvc\Router\Http\Literal',
    'options' => array(
        'route'    => '/application',
        'defaults' => array(
            '__NAMESPACE__' => 'Application\Controller',
            'controller'    => 'Index',
            'action'        => 'index',
        ),
    ),
    'may_terminate' => true,
    'child_routes' => array(
        'minhasubrota1' => $minhasubrrota1,
        'minhasubrota2' => $minhasubrrota2,
        'minhasubrota3' => $minhasubrrota3,
        ...
    ),
);

de forma que cada rota vira um conjunto de subrrotas. Nos exemplos aqui em cima fizemos com rotas tipo 'Literal', mas tanto a rota quanto as subrrotas podem ser de qualquer tipo. E adiantando aqui, subrrotas são uma mão na roda na hora de criar submenus, se é que não foram feitas pensando nisso.

Bom, então, uma vez definidas as rotas , podemos localizar o conteudo de nosso aplicativo. Como a criação de rotas possuem várias possibilidades, crie uns 2 ou 3 controllers e uns 2 ou 3 actions em cada um deles e brinque criando suas rotas. No próximo parte dessa parte faremos uso de links, zf2 navigation e breadcrumbs.

Até lá.

Um comentário:

  1. Velho aqui entendi como funcionam as routes do zf2, parabéns pelo post, muita gente fazendo post inútil, e poucos posts direto ao assunto como o seu.

    ResponderExcluir