Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Lucas Guima

URL amigável

Recommended Posts

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:

Compartilhar este post


Link para o post
Compartilhar em outros sites

bacana @Lucas,

 

só toma cuidado com isso:

http://www.dominio.com/noticia/3
http://www.dominio.com/noticia/3/
http://www.dominio.com/noticias/3
http://www.dominio.com/noticias/3/

pode você pode gerar uma duplicação de conteúdo pro google, e o teu site ser penalizado.

 

Se quer ter essa flexibilidade(não sei pq), use alguns canonicals, para não ter problemas de indexamento.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Aproveitando o assunto levantado, eu acredito que isso não gere duplicidade, pois eu faço o redirecionamento, ou seja, quando ele acessa:

 

http://www.dominio.com/noticia/3
http://www.dominio.com/noticia/3/
http://www.dominio.com/noticias/3
http://www.dominio.com/noticias/3/

a URL final é uma só:

 

http://www.dominio.com/noticia/3

Mesmo assim o Google pode penalizar?

 

E o motivo eu coloquei no post:

 

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.

É a mesma ideia de comprar domínios com grafias semelhantes para garantir que, caso o usuário digite o domínio principal errado, ele ainda sim acesse o site.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pessoal,

 

Sei que esse post é jurássico, mas eu precisava de uma ajudinha de vocês.

Eu configurei esse script em um site, e funcionou td corretamente. Porém, minha pasta /admin/ não funciona nem a pau.

Como faço para criar uma excessão para essas regras?

 

Tentei editando o arquivo url_response.php e não funcionou.

Tentei tb desabilitar o mod_rewrite na pasta /admin/, o que tb não funcionou.

 

Alguém aí tem alguma ideia de como eu faço isso?

 

Obrigado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Imagine o seguinte:

 

Eu tenho um site, e faço o acesso pelo endereço meudominio.com.br.

Com essa função que você compartilhou com a gente, eu consigo tratar qualquer url no formato /algumacoisa para que a mesma referencie-se a um determinado arquivo.

 

Só que preciso colocar, por exemplo, um painel administrativo no subdiretorio /admin, e não quero que as páginas contidas nesse subdiretorio sejam tratadas pela mesma função (o que resultaria em um endereço com final /admin/cadastro.php, por exemplo).

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu tive que fazer algo parecido para utilizar um plugin que passava variáveis via GET, só não tenho o projeto aqui para lembrar em qual arquivo eu fiz o tratamento, mas provavelmente foi no url_response.php, onde você tem a URL acessada.

 

No meu caso ficou hardcoded a comparação com a URL, pulando a verificação das patterns.

Compartilhar este post


Link para o post
Compartilhar em outros sites
Boa Noite Lucas tudo bem? Primeiramente parabéns pela implementação de melhoria da rotina, muito bom. Uma situação que não consigo entender dentro desta estrutura é: imaginemos o endereço: http://site.com.br/area1/area1a/o-titulo-da-noticia (o título é gerado com uma função usando preg_replace para a hifenização do endereço ok?


O endereço não funciona com a pattern: '/area1/area1a/(?P<titulonoticia>\w+)' mas funciona com '/area1/area1a/(?P<titulonoticia>\S+)'.


Basta incluir um hifen e ela para de funcionar com w+, funcionando apenas com S+, porém gera grandes transtornos. Passando pela validação do url_response e caindo no 404.


Saberia me auxiliar a compreender o por que?

Grato.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.