Customização de URLs em projetos MVC – Fazendo o caminho inverso

Update: novo endereço http://rodrigo.cmachado.org/blog/2009/07/customizacao-de-urls-em-projetos-mvc-fazendo-o-caminho-inverso/

Todo framework MVC sério possui um mecanismo de customização de URLs (as vezes chamado de routing). Esse mecanismo permite que tenhamos URLs amigáveis – transformando /carros/ver/35 em /maserati-3200gt.html. Normalmente, isso é implementado utilizando expressões regulares que são mapeadas diretamente para a URL no formato controller/action/parâmetros, o que torna muito simples de ser implementado e configurado. Com as URLs do projeto configuradas, ao desenvolver as páginas temos de optar por colocar os links na forma controller/action/parâmetros (o que não é uma boa idéia, já que estaríamos ignorando a customização de URLs) ou na sua forma customizada (o que claramente é melhor).

Só existe um problema com essa abordagem: vamos imaginar que fosse necessário fazer um ajuste nas URLs no decorrer do desenvolvimento – ou até mesmo imediatamente antes de publicar o projeto. Por menor que seja o ajuste, teríamos de alterar todos os links do projeto (com sorte poderíamos utilizar um script em sed para convertê-las automaticamente, mas ainda sim seria preciso verificar depois se tudo está OK). Foi exatamente esse o problema que enfrentei em um dos projetos que trabalhei recentemente.

Resolver esse problema é mais simples do que parece, mas requer mudanças na forma como as URLs personalizadas são definidas. Na maioria dos frameworks, a configuração é feita dessa forma (ou alguma variação):

<?php
$routes = array(
    '^/([a-zA-Z0-9\-]+)\.html$' => '/carros/ver/$1'
);
?>

Essa abordagem facilita a visualização de quais URLs apontam para onde, mas não permite que façamos o inverso. Ou seja, não conseguiríamos descobrir qual é a URL personalizada para um determinado controller/action. Para isso, vamos tentar decompor melhor essa configuração:

<?php
$routes = array(
    '^/([a-zA-Z0-9\-]+)\.html$' => array(
        'controller' => 'carros',
        'action' => 'ver',
        'params' => array( '$1' )
    );
);
?>

Decompondo a URL de destino nas suas partes básicas (controller, action e parâmetros) podemos escrever um helper que percorre as configurações de URLs procurando pelo controller e action especificados:

<?php
function url_helper($c, $a, array $p) {
    global $routes;

    foreach ($routes as $rota => $info) {
        if ($info['controller'] == $c && $info['action'] == $a) {
            // achamos a rota que queríamos
            // agora executamos o código para montar a URL - isso fica como exercício :)
            break;
        }
    }
}
?>

Podemos ainda expandir esse helper para escolher a URL customizada de acordo com o número de parâmetros envolvidos. A idéia desse post é somente mostrar o caminho para desenvolver essa solução e não fornecer uma implementação completa. Uma outra solução seria rodar um script que modificasse os links nos templates a cada vez que a configuração de rotas fosse modificada.

Publicado em Desenvolvimento, Tecnologia, Web. Tags: , , . Comentários desativados