Escrevendo URLs no Zend Framework

O Zend Framework, assim com os demais frameworks que utilizam o padrão MVC, possui uma estrutura de roteamento para mapear e direcionar corretamente os seus controles e ações de acordo com determinada url requisitada pela aplicação. Também como os demais, possibilita a escrita de urls para estes controles na camada de visualização quando necessário, através dos “helpers”.

Infelizmente, o helper responsável pela escrita dessas urls ainda é bastante imaturo. A forma como deve ser feita esta tarefa é trabalhosa, chata e principalmente, improdutiva. Só o fato de ter de indicar “TODOS” os parâmetros para a escrita da URL em uma estrutura de array associativa soa como um paradoxo, já que o próprio framework possui mecanismos que fazem o parser na url requisitada, identificando os parâmetros necessários e passando-os ao roteador. Ou seja, é um retrabalho e não um reúso. Exemplo de uma url escrita da forma padrão em um arquivo de template.

< ?php
echo $this->url(array(
    'controller' => 'users',
    'action'  => 'edit',
    'id'  => 25
));
?>

A saída do exemplo será: /users/edit/id/25. Analisando a url, seria mais fácil simplesmente escrever da seguinte forma:

< ?php echo "/users/edit/id/25"; ?>

Desta forma o resultado é mais rápido, porém, você perde em termos controle, já que a escrita é manual e se você alterar o nome do controle ou da ação, a url passará a ser inválida (a não ser que você use roteadores customizados).

A maioria dos frameworks, como Symfony, Cake etc, implementam tanto a forma de escrita com os parâmetros em um array, quanto uma string contendo a url desejada, fazendo a conversão automática dos mesmos para o formato padrão do framework ou da aplicação. O Symfony, por exemplo, implementa a escrita da seguinte forma:

< ?php echo url_for('users/edit?id='. 25); ?>

O Symfony automaticamente converterá isso para o formato /users/edit/id/25. Considero essa forma muito mais elegante e produtiva, pois está mais próximo da realidade das urls “dinâmicas”. No entanto, se houver mais parâmetros, a coisa já começa a complicar.

Voltando a forma como o Zend Framework implementa este recurso, já se sabe que ele não é tão flexível assim, então é necessário criar um helper na camada de visualização para esta tarefa. Podemos inclusive, aproveitar o que já foi desenvolvido e é padrão do framework e encontra-se na pasta: Zend/View/Helper/Url.php.

< ?php
require_once 'Zend/View/Helper/Abstract.php';

class Zend_View_Helper_MyUrl extends Zend_View_Helper_Abstract
{ 
     /**
       * Return the URL
       *
       * @param string|array $urlOptions
       * @param string       $name
       * @param bool         $reset
       * @param bool         $encode
       * @return string
       */
       public function myUrl($urlOptions, $name = null, $reset = false, $encode = true)
       {
          $front  = Zend_Controller_Front::getInstance();
          $router = $front->getRouter();

          if (is_string($urlOptions)) {
             $urlOptions = '/'. ltrim($urlOptions, '/'); // Case the first character is a '?
             $request = new Zend_Controller_Request_Http(); // Creates a cleaned instance of request http
             $request->setBaseUrl($front->getBaseUrl());
             $request->setRequestUri($urlOptions);
             $route = $router->route($request); // Return the request route with params modifieds
             $urlOptions = $route->getParams();
          }
 	  return  $router->assemble((array) $urlOptions, $name, $reset, $encode);
      }
 }

Salvo o helper, é só utilizá-lo. Agora ele suporta todos os formatos:

< ?php echo $this->myUrl(array(
   'controller'=> 'users',
   'action' => 'edit',
   'id'  => 25
)); ?>

ou

< ?php echo $this->myUrl('users/edit?id=25'); ?>

ou

< ?php echo $this->myUrl('users/edit/id/25'); ?>

Muito mais simples, elegante e bem produtivo!

É possível ainda utilizar os outros parâmetros do helper padrão, como o nome do roteador a ser utilizado para formatar a url, se o mesmo vai ou não utilizar a url base ou somente a partir da atual e se a url será codificada ou não – bastante útil para utilizar como valor de outros parametros. ;-)

Até a próxima.

8 ideias sobre “Escrevendo URLs no Zend Framework

  1. Marcelo andrade

    Gostei! O ZF não é minha ferramenta de opção, mas tive de trabalhar com ele num projeto. Acabamos ficando com as urls literais que era o mais fácil. Sem dúvida, esta dica já teria nos ajudado.

  2. DANIEL MAFFIOLETTI

    Imagine um analfabeto no linux, tentando instalar e configurar o Zend Framework. Sou eu, estou apanhando feio, 7 x 0 pra instalação. Marcelo, talvez seja ridículo a minha sugestão, mas tenho vasculhado na internet e não consigo encontrar um manual para leigos. A maioria dos conteúdos encontrados de ZF para linux, são abordados com um nível técnico intermediário em Linux.

    Como não tenho muita intimidade com o Terminal do Linux, eu não estou conseguindo criar o projeto, configurar o apache e etc.

    Sei que é detalhes, mas deixo a uma sugestão!!!
    abraços

  3. Thiago

    Muito boa essa função. Eu tava pensando em fazer uma também, exatamente pelo mesmo motivo. Já estou usando a sua. ^^

    Nomeei meu helper como Url mesmo, pra reescrever o do zend.

    Bom, encontrei um bug na estrutura do seu if().
    Se eu estiver na página: “/Search?s=produto” e na página tiver qualquer Url nesse formato: Url(‘users/edit?id=25′) ?>, irá retornar: Users/edit/id/25/s/produto. Ou seja, o get da página corrente, está sendo incluído no Url.

    Inicialmente criei uma função pra tirar o que não deveria entra, porém, quando conclui, notei que um simples $_GET=array(); já teria resolvido. ¬¬
    Incluindo esse GET na primeira linha dentro do if() resolve. ;D

    Fiz outra modificação também, pra uma barra no final do URL. (acho estranho sem)

    Valeu

  4. Wanderson Camargo

    Faça algo parecido com um Singleton do Request, tornando o auxiliar de visualização mais rápido. Criar um objeto sempre que este elemento é executado demora muito mais do que trabalhar somente com um objeto na memória. Uma pergunta que faço é se esse auxiliar trabalha bem quando existe uma rota diferente. Abraços!

Deixe uma resposta