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!