Otimizando as URL’s na hora de migrar um site em PHP para CakePHP

Olá pessoal,

nestes dias fui chamado para fazer um refactory de um dos primeiros sites que desenvolvi. Na época eu não me preocupava com URL’s amigáveis nem coisa semelhante. Para ser sincero, nem sabia do que se tratava.

O site havia sido desenvolvido inteiramente usando chamadas diretas para os scripts PHP, como por exemplo: noticias_ler.php?id=id_da_noticia.

Como uma das características que seriam agragadas a nova versão do site seria a otimização e uso de URL amigáveis, eu não poderia deixar do jeito que estava. Aliás, eu usaria o CakePHP no projeto, então, sem chances de manter como estava.

A primeira coisa eu me veio a cabeça foi mudar pra CakePHP. Não pensei nas consequências disso. Refletindo um pouco mais, vi que uma mudança radical em todas as URL’s do site poderia não ser uma coisa bacana, já que o mesmo já contava com mais de 40.000 notícias dentre outros conteúdos. Já que todos os links antigos deixariam de funcionar. Isso não seria uma boa para motores de busca, nem mesmo para quem colocou uma determinada notícia no favoritos, por exemplo.

Logo, imaginei que eu teria que redirecionar todas as URL’s (pelo menos as mais importantes) para o novo formato. Mas eu queria redirecionar algo como: noticia_ler.php?id=10 para /noticias/ler/10/titulo-da-noticia-bonito.

A primeira coisa que fiz foi rotear no routes.php a URL noticia_ler.php para um controller qualquer (ou para o controller Noticias). No exemplo a seguir, redirecionei para o controler redireciona.

  1. Router::connect('/noticia_ler.php*', array('controller' => 'redireciona', 'action' => 'noticia'));

O controller Redireciona na verdade não precisaria nem existir, poderia ter feito dentro do próprio noticias. Mas a minha idéia era contralar todos os redirects de um único controller.

Na action noticia do controller Redireciona:

  1. $id = $this->params["url"]["id"];
  2. $n = $this->Noticia->findById($id);
  3. $slug = Inflector::slug($n["Noticia"]["titulo"]); // retira acentos e etc
  4. $slug = strtolower($slug); // passa pra minusculo
  5. $slug = str_replace("_", "-", $slug); // troca _ por -
  6. $this->redirect("/noticias/ler/".$id."/".$slug, 301, true);

Detalhe do uso do método slug da classe Inflector, que retira todos os caracteres especiais e espaços para a construção de URL’s amigáveis, transformando, por exemplo, “Tulio Faria” em “Tulio_Faria”. Em seguida faço algumas transformações para ficar no formato que gosto: “tulio-faria”, tudo minúsculo e separado por hífem.

O segundo paramêtro do redirect é o código de redirecionamento a ser usado, no caso do 301 é Movido Permanentemente. O terceiro paramêtro indica que será dado um exit() após o redirecionamento.

Bom pessoal, é isso!

Espero que isso ajude-os assim como me ajudou! Qualquer dúvida, comentem!

Forte abraço!

8 Comment

  1. Olá Túlio,

    Só para lembrar, você pode passar um 2º parâmetro no método Inflector::slug contendo a string de troca, no seu caso o hífen.

    http://api.cakephp.org/class/inflector#method-Inflectorslug

    Abraços.

  2. Olá,
    Parabéns pelo trabalho..
    Esse blog está nos meu favoritos e ira me ajudar bastante!!
    Nunca tinha trabalhado com frameworks e agora que estou vendo a maravilha que são.
    Comecei usando o Spaghetti, que é brasileiro muito parecido com o Cake,,
    No meu próximo projeto usarei o Cake que é bem mais poderoso!
    Abraços!!

  3. Olá Tulio,

    Eu sempre trabalhei com o trio adodb, smarty e jquery nas minhas aplicações PHP.

    Me sobrou um tempo aqui na empresa e estou conhecendo o cakephp. Estou achando muito interessante, mas tenho algumas dúvidas que acho que você pode me ajudar:

    No CakePHP, o crud funciona muito bem, mas nas aplicações corporativas, os sqls são mais complexos, buscando dados de varias tabelas, e as vezes utilizando-se de facilidades de um banco especifico, e não o sql ansi padrão. da pra criar consultas mais complexas com o CakePHP ? acredito que sim, mas como você faz isso ?

    Fiquei descepicionado com a camada view do cake, é ‘echo’ pra todo lado. 🙂 eu descobri que da pra incorporar o smarty no cake, mas seguindo as instruções eu não consegui. você já tentou ? sabe como fazer isso ?

  4. @ TULIO FARIA
    Porque você usou str_replace ao invés de simplesmente?

    1. Inflector::slug($n["Noticia"]["titulo"], '-' );

    Falopa!

  5. Túlio, vlw pela dica. Estava com um problema parecido, mas consegui solucioná-lo com a sua ajuda. Porém agora o meu problema é com cache. A questão é que o cache gerado fica com o nome apenas do controller, como por exemplo “buscar”, ao invés de “buscar_alguma_coisa”. Você tem alguma dica?
    Agradeço desde já.

  6. Tulio, Um tempo atras desenvolvi um fotolog em php com ferramentas de desenvolvimento próprias, e acabei conhecendo o Cake a pouco tempo. Hoje estou tentando migrar sabendo que URLs deveriam ficariam assim:
    http://www.meufotolog.com/NOMEUSER

    E no padrão cake é assim:
    http://www.meufotolog.com/usuario/NOMEUSER

    Haveria algum modo de contornar isso ?

    sabendo que este ‘NOMEUSER’ da URL irá fazer uma consulta ao Mysql.
    Fico no aguardo.

  7. Ola tulio, eu gostaria de saber como é qu eu faço a seguinte rota, sem interferir com o scaffold e outros controllers:

    http://www.domain.com/NOMEDEUSUARIO

    http://www.domain.com/NOMEDEUSUARIO/CONTROLLER

    http://www.domain.com/NOMEDEUSUARIO/CONTROLLER/ACTION

Deixe uma resposta