URL amigável
Olá a todos, vou compartilhar uma solução que julguei ser a melhor forma de trabalhar com URLs amigáveis.
Eu tomei como base um artigo do iMaster escrito pelo Camilo Teixeira de Melo sobre o assunto.
Em resumo, a função do artigo vincula um arquivo a uma URL. Quando chamada, inclui-se o respectivo arquivo.
Exemplificando, vou utilizar o mesmo que tem lá:
http://www.dominio.com/noticias
inclui
http://www.dominio.com/applications/noticias.php
Porém, fazendo alguns testes eu encontrei pontos que poderiam ser melhorados, no sentido de tratar possíveis erros do usuário. Por exemplo, se você adiciona uma barra no final, já não funciona:
http://www.dominio.com/noticias/
Isso eu considero um erro aceitável, isto é, se for considerado um erro. E sendo um pouco mais tolerante, algumas palavras trocadas poderiam ser aceitas. Exemplo:
http://www.dominio.com/noticia
querendo dizer
http://www.dominio.com/noticias
Ou ainda:
http://www.dominio.com/noticias/3
querendo dizer
http://www.dominio.com/noticia/3
Com esse intuito, fiz algumas modificações para que essas situações fossem abrangidas.
:seta: Observação antes de começar:
- Recomendo implementar a função do artigo citado antes desta para entender a lógica e aí sim, aplicar as alterações sugeridas abaixo.
Seguem os arquivos:
.htaccess
RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ main.php
:seta: Sem alterações
config.php
<?php
define('EXTRA_URL', '/site/');
define('BASE_URL', 'http://' . $_SERVER['HTTP_HOST'] . EXTRA_URL);
define('BASE_PATH', $_SERVER['DOCUMENT_ROOT'] . EXTRA_URL);
?>
:seta: Esse arquivo foi criado com as opções básicas da implementação com caminhos absolutos que uso. O EXTRA_URL refere-se às pastas além do domínio, caso a raíz do projeto não seja a raíz do servidor.
urlResponse.php
<?php
require 'config.php';
if(!defined('REQUEST_URI'))
{
$extraUrl = preg_replace('/\/$/', '', EXTRA_URL);
$requestUri = str_replace($extraUrl, '', $_SERVER['REQUEST_URI']);
define('REQUEST_URI', $requestUri);
}
function urlResponse($urlPatterns, $altUrlPatterns){
$destiny = '';
foreach($urlPatterns as $pattern => $file)
{
if(preg_match("@^{$pattern}$@", REQUEST_URI, $_GET))
{
$destiny = $file;
break;
}
}
if (!empty($destiny))
{
include BASE_PATH . $destiny;
exit();
}
$redirect = '';
foreach($altUrlPatterns as $pattern => $url)
{
if(preg_match("@^{$pattern}$@", REQUEST_URI, $_GET))
{
$redirect = preg_replace('/^\//', '', $url);
break;
}
}
if (!empty($redirect))
{
$getKeys = array_keys($_GET);
$getKeys = preg_grep('/^[1-9]*$/', $getKeys);
$parameters = '';
if (count($getKeys) > 0)
{
foreach($getKeys as $getKey)
{
$parameters .= '/' . $_GET[$getKey];
}
}
header('Location: ' . BASE_URL . $redirect . $parameters);
exit();
}
include('404.php');
}
?>
:seta: O que mudou?
- Incluído o arquivo de configuração (config.php) e como as constantes foram definidas lá, as outras verificações foram retiradas.
- O arquivo de configuração eu costumo utilizar no restante do site da maneira que está lá, porém no tratamento da URL é necessário tratar uma vez mais de acordo com a mecânica da função, retirando a barra ao final.
- Já dentro da função, é verificado se a URL coincide com alguma das patterns. Se sim, inclui o respectivo arquivo e finaliza.
- Em caso negativo, ele verifica se coincide com o segundo array, se sim, ele redireciona para a respectiva URL recolocando os parâmetros.
- Em último caso, inclui uma página de erro 404.
main.php
<?php
include 'urlResponse.php';
$urlPatterns = array(
'/noticias/?' => 'pages/noticias/index.php',
'/noticia/(?P<idNoticia>\d+)/?' => 'pages/noticias/noticias.php',
'/' => 'pages/index.php'
);
$altUrlPatterns = array(
'/noticia/?' => '/noticias',
'/noticias/(?P<idNoticia>\d+)/?' => '/noticia'
);
urlResponse($urlPatterns, $altUrlPatterns);
?>
:seta: O que mudou?
- Ao final das patterns foi adicionada a condição /?, indicando que a URL pode ou não ter uma barra no fim.
- Criado um novo array para especificar as possibilidades de erro. Com a seguinte estrutura: URL aceitável => URL sem parâmetros correta.
Pronto! :D
:seta: Concluindo:
http://www.dominio.com/noticias
é acessada por
http://www.dominio.com/noticias
http://www.dominio.com/noticias/
http://www.dominio.com/noticia
http://www.dominio.com/noticia/
E:
http://www.dominio.com/noticia/3
é acessada por
http://www.dominio.com/noticia/3
http://www.dominio.com/noticia/3/
http://www.dominio.com/noticias/3
http://www.dominio.com/noticias/3/
O código pode não ter ficado da melhor maneira, mas eu obtive o que esperava. Espero que possa ser útil de alguma forma. :thumbsup:
Discussão (7)
Carregando comentários...