Acho que já falei aqui sobre a minha paixão pelo Ruby on Rails, um framework de Ruby que me fez enxergar o desenvolvimento web de uma forma bem diferente. Percebi que as coisas poderiam ser feitas de uma forma muito mais rápida. Há cerca de 3 semanas comecei a trabalhar com o framework CakePHP, que é uma cópia do Ruby on Rails para a linguagem PHP, e nesse pouco tempo já aprendi algumas coisas que posso compartilhar.
Essa semana um trouxa moço muito simpático aqui do trabalho queria uma forma de redirecionar pra uma certa página caso o usuário digitasse um endereço inexistente dentro do site criado com o cake. A primeira coisa que se pensa é procurar um jeito de fazer isso através das rotas, mas eu procurei e não encontrei nenhuma forma de criar uma rota específica para controllers ou actions não existentes.
Como fazer, então? A solução é usar um misto dos recursos do Cake, com o básico do próprio PHP. Que venha a nós o beforeFilter e a herança de classes.
Como Redirecionar Endereços Inválidos
O CakePHP permite que você defina um método beforeFilter nos seus controllers, que será chamado antes da action (método do controller) ser chamada pelo framework. E como queremos que TODOS os nossos controllers saibam responder a um endereço inexistente, a melhor opção é criar o método beforeFilter no app_controller.php
Se seu projeto no cake ainda não tem o app_controller, é só você criar um arquivo chamado app_controller.php dentro da pasta app (e não na pasta controllers), e dentro dele colocar o código:
<?php
class AppController extends Controller {
}
?>
E dentro da classe vamos adicionar nosso beforeFilter:
<?php
class AppController extends Controller {
function beforeFilter() {
if( !empty($this->params['action']) && !method_exists($this, $this->params['action']) ) {
$this->redirect(array('controller' => 'main', 'action' => 'missing'));
}
}
}?>
O que fizemos acima? A função method_exists é um recurso do PHP que testa se um método existe em um dado objeto. Passamos $this como o objeto, e $this->params['action'] como o método a testar. Se retornar false significa que a action não existe, e o usuário está tentando acessar uma action inexistente. Então o beforeFilter redireciona o usuário pra um lugar que realmente existe, antes mesmo que o framework tente chamar a action. Do exemplo acima, você pode trocar o controller ‘main’ e a action ‘missing’ pelo que for melhor para o seu projeto. Basta ter certeza de que está redirecionando pra um controller e uma action que realmente existam.
Note que isso só funciona se o usuário tentar acessar um endereço que aponte para uma action inválida, mas em um controller válido. Se o usuário acessar apenas site.com/pudim, o CakePHP vai buscar um controller pudim e aí vai dar erro mesmo. Uma solução possível seria criar uma rota definindo que caso acessem um endereço com apenas um parâmetro depois do domínio, ele redirecione pra um controller específico e passe aquele parâmetro único como rota. Pra quem não sabe configurar as rotas, amanhã eu explico.