Catégories
PHP

404 parfaites dans CakePHP

Une fois n’est pas coutume, aujourd’hui on ne parle pas SEO mais PHP.
Vous aimeriez bien obtenir autre chose que des « MissingView » et « MissingController » dans CakePHP lorsque vous tapez une url ne faisant référence à aucun controller (sans pour autant passer la variable de debug à 0 dans le core.php) ?
Cet article est pour vous, il est destiné à la gestion parfaite des 404 avec CakePHP.
Pourquoi parfaite, alors que CakePHP dispose de sa classe de gestion d’erreurs ? Et bien parfaite pour 2 raisons. La première est de pouvoir gérer les erreurs que l’on souhaite (dans notre cas les « MissingView » et « MissingController »), et la deuxième, elle est tout simplement primordiale pour le SEO, retourner un code d’erreur 404 lors d’une erreur 404 (alors que CakePHP retourne un code 200).
Vous êtes prêts, alors on y va.

Création de la vue et du Layout

Etant donné que cet article s’adresse aux développeurs utilisant cakePHP, je ne vais pas expliquer tout le principe de fonctionnement de ce dernier. Je suppose que vous êtes à l’aise avec le motif MVC.

Je vais donc commencer par créer mon layout dédié pour l’affichage des erreurs. Reprenez si besoin votre layout « default » pour ne pas vous prendre la tête. Donc dans {app}/views/layouts, je crée un error.ctp (qui comme je l’ai dis précédemment peut être une copie de votre default.ctp).
La seule difference par rapport à mon default.ctp, c’est que je vais dire à google de ne pas indexer mes 404 (certains sont pour, d’autre contre, pour ma part je n’ai pas besoin de Google pour trouver mes pages d’erreur, je check mes 404 avec linklint). Pour cela, j’ajoute dans mon head :

<meta name="robots" content="noindex" />

Maintenant que nous avons crée notre layout pour afficher nos erreurs, créons donc la vue qui va avec. Pour cela, je reste basique, à vous de personnaliser à votre guise.
Création donc de {app}/views/errors/error404.ctp

<p>La page demandée n'existe pas</p>

Surchage de la classe ErrorHandler

C’est à partir de maintenant que tout va se jouer !! Si on utilise dans notre controller, le bon vieux :

$this->cakeError('your_error_view');

on va vite se rendre compte en analysant les entêtes HTTP que ce filou nous renvoie un code 200 (et ça c’est pas bon).
Pour palier à ce probleme, nous allons tout simplement surcharger la classe ErrorHandler.
Pour se faire, sachez que cakePHP est terrible pour cela, car il vous suffit de créer un fichier « error.php » dans votre dossier {app}, tout comme le « app_controller.php », mais ca nous y reviendrons par la suite. Nous allons donc créer le fichier {app}/error.php et y mettre ceci :

<?php
// {app}/error.php
class AppError extends ErrorHandler {
 
	function __construct($method, $messages)
	{
		$params = Router::getParams();
 
		// Comme dis dans l'exemple, on veut une 404 pour les 2 methodes suivantes
		if ($method == 'missingController' || $method == 'missingView')
		{
			// Ca c'est une methode custom pour gerer l'affichage
			$this->missingControllerorView($params);
		}
		else
		parent::__construct($method, $messages);
 
	}
 
	// La methode custom en question
	function missingControllerorView($params)
	{
		$this->controller =& new AppController();
		$this->controller->_set(Router::getPaths());
		$this->controller->params = $params;
		$this->controller->constructClasses();
		$this->controller->viewPath = $params['controller'];
		header("HTTP/1.0 404 Not Found");
		$this->controller->render('/errors/error404', 'error');
		e($this->controller->output);
		exit;
	}
}
?>

Vous avez surement du trouver moultes exemples à travers la toile vous expliquant cette méthode, mais comme je vous l’ai dis, ces méthodes ne renvoient pas de code 404. Ici, grâce à la fonction header(), on va forcer un peu la main à notre copain cakePHP.

Appel dans notre app_controller

Maintenant que tout ceci est fait, il ne nous reste plus qu’à tester dans notre app_controller que le moteur de cakePHP ne nous a pas renvoyé un « CakeError ». Ça pourra éviter ce type de surprise.

<?php
// {app}/app_controller.php
class AppController extends Controller
{
 
	function _setErrorLayout() {
		if ($this->name == 'CakeError')
		{
                        // Si on a une erreur, on utilise notre layout crée au début de l'article
			$this->layout = 'error';
		}
	}
 
        // On effectue un test avant de rendre la vue
	function beforeRender () {
		$this->_setErrorLayout();
	}
 
}
?>

Testez vos paramètres dans vos controllers

Bon et bien la je ne vais pas vous apprendre le pourquoi du comment. Je vais juste prendre un exemple bidon pour vous montrer comment appeler notre page d’erreur.
Admettons que vous ayez une fonction pour afficher vos produits dans votre controller « ProductsController », la méthode sera alors la suivante :

<?php
{app}/controllers/products_controller.php
// Nous sommes bien d'accord qu'il s'agit d'un exemple
function display_product($id_product=null)
{
// On verifie la validite des donnees -> sinon erreur 404
if(!$id_product || !is_numeric($id_product))
{
       // Le 2eme parametre est tres utile si vous utilise l'url-rewriting
      // Vous pouvez laisse tel quel, meme sans url-rewriting
	$this->cakeError('error404', array(array('url' => $this->action)));
}
 
// Et la votre jolie code pour afficher votre produit
 
}
?>

Voila, maintenant vous êtes armés pour afficher de VRAIES erreurs 404 dans cakePHP.

2 réponses sur « 404 parfaites dans CakePHP »

Merci pour cette contrib, je vais garder ça au chaud pour mon développement d’appli en cours.
Cool de voir que tu utilises le best framework ever (troll inside). Tu as compris le système d’ARO/ACO ?
Moi c’est le seul truc sur lequel je bloque total…

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *