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.
Muito interessante! Não costumo trabalhar com o Zend, mas andei estudando seu funcionamento. Parabéns pelo artigo!
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.
salvou a lavoura
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
cara, excelente seu blog, parabens!
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
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!
Bom artigo.