Back-End

14 ago, 2007

URLs Amigáveis – Algumas Técnicas

Publicidade

Olá leitores. No último artigo mostrei as vantagens, desvantagens e dicas das URLs Amigáveis, ou Friendly URLs. Vimos que a utilização de URLs Amigáveis torna nossas aplicações mais profissionais e facilitam o entendimento dos usuários, melhoram a aparência das URLs e melhoram a indexação pelos mecanismos de busca.

Hoje mostrarei as três técnicas que conheço para tornar as suas URLs mais amigáveis. Cada uma tem vantagens e desvantagens, como vocês verão, mas o importante é que uma delas seja implementada.

Conheço três técnicas: PATH_INFO, Error Pages e MOD_REWRITE.

Se você ainda está em dúvida do que é uma URL Amigável e se você deve ou não usá-la, dê uma olhada no artigo anterior: URLs Amigáveis – Vantagens, Desvantagens e Dicas.

Os exemplos deste artigo estão direcionados para o PHP e Apache, mas acredito que seja possível converter essas técnicas para utilização em outras linguagens server-side e/ou servidor web.

Nota:

Todos os exemplos dependem de acesso à configuração do servidor Apache e/ou que a diretiva AllowOverride (arquivo httpd.conf) não esteja setada como None.

PATH_INFO

Um exemplo de URL Amigável feita através da utilização de PATH_INFO:

http://www.seusite.com.br/artigo.php/27/2

Vamos supor que essa URL o levasse para o artigo 27, em sua página 2.

Você deve ter percebido que, aparentemente, há um erro, pois temos uma estrutura de pastas após o arquivo. Mas isso não gera erro se a diretiva AcceptPathInfo estiver habilitada na configuração do servidor Apache. Caso ela não esteja habilitada no arquivo httpd.conf do seu servidor ou você não puder alterá-lo, você pode habilitar essa diretiva através da inserção da linha de código abaixo no arquivo .htaccess.

AcceptPathInfo On

Se esta diretiva estiver habilitada e a URL acima for acessada, será gerada pelo servidor a variável $_SERVER[“PATH_INFO”]. Pelo exemplo acima, essa variável teria o seguinte valor: “/27/2´´, e o arquivo acessado no servidor seria o artigo.php.

Seguindo a lógica de que o valor entre as primeiras barras refere-se ao ID do artigo e que o segundo valor se refere à página a ser exibida, dê uma olhada no script abaixo (Observe os comentários):

<?php
/**
* Inicializa as variáveis com valores padrão (default)
*/
$artigo = 1;
$pagina = 1;
/**
* Testa se a variável PATH_INFO existe
*/
if ( isset( $_SERVER["PATH_INFO"] ) ) {
    /**
    * Transforma a string da variável PATH_INFO num array (vetor)
    */
    $arr = explode( "/", $_SERVER["PATH_INFO"] );
    /**
    * Percorre todos os ítens do array atribuindo o índice à variável $chave o o conteúdo deste índice à variável $valor
    */
    foreach ( $arr as $chave => $valor ) {
        /**
        * Elimina do array os valores "em branco"
        */
        if ( empty( $valor ) ) {
            unset( $arr[$chave] );
        }
    }
    /**
    * Reinicializa os índices do array a partir do 0
    */
    $arr = count( $arr ) ? array_merge( $arr ) : null;
    /**
    * Passa os valores para as respectivas variáveis
    */
    $artigo = isset( $arr[0] ) ? $arr[0] : 1;
    $pagina = isset( $arr[1] ) ? $arr[1] : 1;
}
/**
* Exibe as variáveis
*/
echo "Código do artigo: ".$artigo."\n";
echo "Página do artigo: ".$pagina."\n";
?>

Como pôde ser visto, não utilizamos query string e passamos os valores para as variáveis, corretamente.

Desvantagens:

  • Alguns sistemas de busca identificam essa URL como mal gerada e a ignoram. O Google identifica normalmente.
  • Ela não abstrai a tecnologia empregada.
  • Depende da configuração da diretiva AcceptPathInfo, do Apache.

Error Pages

Um exemplo de URL Amigável feita através da utilização de Error Pages: http://www.seusite.com.br/artigo/27/2

Não mudou quase nada, não é mesmo? Mas pelo menos já abstraímos a tecnologia empregada, facilitando a sua substituição.

A aplicação desse método também envolve a configuração do servidor Apache ou a inserção da linha abaixo no arquivo .htaccess.

ErrorDocument 404 /processador.php

A linha acima diz para o servidor que, se a página requirida não for encontrada (gerando erro 404), deverá ser acessado o arquivo processador.php, que está na raiz do servidor.

Agora, ao invés de utilizarmos a variável PATH_INFO, utilizaremos a variável REQUEST_URI. Esta variável, armazena, para o nosso exemplo, o valor “/artigo/27/2´´.

Como essa estrutura de diretórios não existe, ocorrerá um erro 404 ao tentarmos acessar essa URL. Quando for gerado esse erro, o Apache redirecionará a requisição para o arquivo processador.php, conforme indicado no .htaccess.

Supondo que na regra estabelecida o primeiro valor entre as barras seja o arquivo que deve ser acessado, o segundo valor refere-se à identificação do artigo e o terceiro à página do artigo, temos o código abaixo:

<?php
/**
* Retira o erro 404 do cabeçalho do documento, informando ao servidor que está tudo OK.
*/
header("HTTP/1.1 200 OK");
/**
* Inicializa as variáveis com valores padrão (default)
*/
$arquivo = "index.php";
$artigo = 1;
$pagina = 1;
/**
* Testa se a variável REQUEST_URI existe
*/
if ( isset( $_SERVER["REQUEST_URI"] ) ) {
    /**
    * Transforma a string da variável REQUEST_URI num array (vetor)
    */
    $arr = explode( "/", $_SERVER["REQUEST_URI"] );
    /**
    * Percorre todos os ítens do array atribuindo o índice à variável $chave o o conteúdo deste índice à variável $valor
    */
    foreach ( $arr as $chave => $valor ) {
        /**
        * Elimina do array os valores "em branco"
        */
        if ( empty( $valor ) ) {
            unset( $arr[$chave] );
        }
    }
    /**
    * Reinicializa os índices do array a partir do 0
    */
    $arr = count( $arr ) ? array_merge( $arr ) : null;
    /**
    * Passa os valores para as respectivas variáveis
    */
    $arquivo = isset( $arr[0] ) && file_exists( $arr[0].".php" ) ? $arr[0] : "index.php";
    $artigo = isset( $arr[1] ) ? $arr[1] : 1;
    $pagina = isset( $arr[2] ) ? $arr[2] : 1;
}
/**
* Exibe as variáveis
*/
echo "Nome do arquivo: ".$arquivo."\n";
echo "Código do artigo: ".$artigo."\n";
echo "Página do artigo: ".$pagina."\n";
?*#62;

Claro que, ao invés de você exibir as variáveis, você deve redirecionar para o arquivo encontrado e passar as variáveis (através de GET, SESSION ou COOKIE).

Desvantagens:

  • Todo o processamento será feito sempre pelo mesmo arquivo.
  • Pela desvantagem acima, deve-se adotar uma regra excelente para conversão das variáveis.
  • Depende da configuração do Apache.
  • O log de erros do servidor fica inutilizado, pois a cada acesso será gerado um registro de erro.

MOD_REWRITE

Está técnica é a mais usada, certamente, por permitir mais flexibilidade e facilidade de manutenção. Porém, ela depende diretamente da configuração do arquivo httpd.conf (configuração do Apache), onde é necessária a habilitação do módulo Mod_Rewrite.

Vamos começar então pela configuração do servidor Apache:

Localize as linhas abaixo no arquivo httpd.conf (não necessariamente uma abaixo da outra).

#LoadModule rewrite_module modules/mod_rewrite.so
#AddModule mod_rewrite.c

Caso não exista(m), adicione.

Retire o caractere # do início de cada linha. Este caractere serve para fazer comentários no arquivo de configuração do Apache.

Localize as linhas:

<Directory />
    Options FollowSymLinks
    AllowOverride None
</Directory>

Substitua a palavra None, depois de AllowOverride para All, ficando assim:

<Directory />
    Options FollowSymLinks
    AllowOverride All
</Directory>

Isso permitirá a reescrita dos diretórios.

Salve o arquivo e reinicie o servidor.

Agora, crie um arquivo .htaccess na raiz do servidor com o conteúdo (observe que os comentários começam com #):

#Executa se o módulo estiver carregado no servidor
<IfModule mod_rewrite.c>
#Habilita o Módulo de Reescrita
RewriteEngine On
#Define a pasta da raiz
RewriteBase /
#Se a URL apontar para um arquivo, vai diretamente para ele
RewriteCond %{REQUEST_FILENAME} !-f
#Se a URL apontar para uma pasta, vai diretamente para ela
RewriteCond %{REQUEST_FILENAME} !-d
#Vou explicar no texto do artigo
RewriteRule ^artigo/([^/]*)(/([^/]*)/?)?$ artigo.php?cod=$2&pag=$4 [L]
RewriteRule ^([^/]*)/([^/]*)(/([^/]*)/?)?$ $1.php?cod=$2&pag=$4 [L]
</IfModule>

Na linha do RewriteRule (que pode ter várias), utilizei Expressões Regulares para fazer a substituição da URL Amigável pela URL com query string (mas o usuário vê a URL Amigável). Como não é objeto desse artigo, não explicarei sobre expressões regulares. Veja o link na seção Referências, para aprender um pouco mais sobre RegEx.

O [L] no final da linha do RewriteRule indica que se a expressão regular “casar” com a URL entrada, o script deve parar ali. A ausência do [L] é útil se você quiser que sejam feitos vários “casamentos”.

Utilizando esse .htaccess na raiz do servidor, poderemos fazer a seguinte relação:

http://www.seusite.com.br/artigo/ = http://www.seusite.com.br/artigo.php?cod=&pag=|

http://www.seusite.com.br/artigo/27 = http://www.seusite.com.br/artigo.php?cod=27&pag=|

http://www.seusite.com.br/artigo/27/ = http://www.seusite.com.br/artigo.php?cod=27&pag=|

http://www.seusite.com.br/artigo/27/2 = http://www.seusite.com.br/artigo.php?cod=27&pag=2|

http://www.seusite.com.br/artigo/27/2/ = http://www.seusite.com.br/artigo.php?cod=27&pag=2|

http://www.seusite.com.br/livro/ = http://www.seusite.com.br/livro.php?cod=&pag=|

http://www.seusite.com.br/livro/27 = http://www.seusite.com.br/livro.php?cod=27&pag=

Perceberam a facilidade??

No arquivo artigo.php você só precisa testar se as variáveis “cod” e “pag” estão vazias (empty).

Desvantagens:

  • Depende da configuração do Apache.

Cuidado:

Aa segunda linha do RewriteRule pode ser “perigosa”: como ela requisita o arquivo do mesmo nome digitado pelo usuário, se ele digitar o nome de um arquivo inexistente, ocorrerá um erro 404.

Conclusão

Como podem ver, cada uma tem vantagens e destantagens. Porém, a utilização do MOD_REWRITE tem uma só desvantagem e que é comum às outras técnicas apresentadas: depender da configuração do Apache.

Assim, eu prefiro e indico a terceira forma.

Outra “desvantagem” dessa técnica é que é preciso sacar um pouco de expressões regulares. Mas não listei isso nas desvantagens e coloquei agora entre aspas porque isso não é inerente à técnica de reescrita de URLs com Mod_Rewrite. Quem estiver confuso sobre a RegEx, deve dar uma olhada no link da seção Referências.

Espero ter ajudado com essa concentração de técnicas, principalmente porque as duas primeiras são pouco exploradas e também é difícil achá-las todas reunidas.

Deixe uma mensagem nessa caixinha aí em baixo! Abraços!