Exceptions

Les Exceptions peuvent être utilisées pour une variété d’utilisations dans votre application. CakePHP utilise les exceptions en interne pour indiquer les erreurs logiques ou les erreurs d’utilisation. Toutes les exceptions levées de CakePHP étendent CakeException, et il y a des exceptions spécifiques selon les classes/tâches qui étendent la classe de base.

CakePHP fournit aussi un nombre de classes d’exceptions qui peuvent être utilisées pour les erreurs HTTP. Regardez la section sur Exceptions intégrées pour CakePHP pour plus d’informations.

Configuration de Exception

Il y a certaines clés disponibles pour configurer les exceptions:

Configure::write('Exception', array(
    'handler' => 'ErrorHandler::handleException',
    'renderer' => 'ExceptionRenderer',
    'log' => true
));
  • handler - callback - Le callback pour gérer les exceptions. Vous pouvez définir ceci pour n’importe quel type de callback, incluant les fonctions anonymes.

  • renderer - string - La classe responsable du rendu des exceptions non attrapées. Si vous choisissez une classe personnalisée, vous devriez placer ce fichier pour cette classe dans app/Lib/Error. Cette classe a besoin d’implémenter une méthode render().

  • log - boolean - Quand à true, les exceptions + leurs stack traces seront logged à CakeLog.

  • consoleHandler - callback - The callback used to handle exceptions, in a console context. If undefined, CakePHP’s default handler will be used.

Le rendu d’Exception par défaut affiche une page HTML, vous pouvez personnaliser soit le gestionnaire soit le rendu en changeant les configurations. Changer le gestionnaire, vous permet de prendre le contrôle total sur le processus de gestion d’exception, tandis que changer le rendu vous permet de changer facilement la sortie type/contenu, ainsi que d’ajouter une gestion d’exception spécifique dans l’application.

Nouveau dans la version 2.2: L’option Exception.consoleHandler a été ajoutée dans 2.2.

Classes d’Exception

Il y a un certain nombre de classes d’exception dans CakePHP. Chaque exception remplace un message d’erreur cakeError() du passé. Les Exceptions offrent une flexibilité supplémentaire dans laquelle elles peuvent étendre et contenir de la logique. L’exception intégrée va capturer toute exception non attrapée et rendre une page utile. Les Exceptions qui n’utilisent pas spécifiquement un code 400, seront traitées comme une Erreur Interne du Serveur.

Exceptions intégrées pour CakePHP

Il y a plusieurs exceptions intégrées dans CakePHP, en-dehors des exceptions internes du framework, il y a plusieurs exceptions pour les méthodes HTTP.

exception BadRequestException

Utilisé pour faire une erreur 400 de Mauvaise Requête.

exception UnauthorizedException

Utilisé pour faire une erreur 401 Non Autorisé.

exception ForbiddenException

Utilisé pour faire une erreur 403 Interdite.

exception NotFoundException

Utilisé pour faire une erreur 404 Non Trouvé.

exception MethodNotAllowedException

Utilisé pour faire une erreur 405 pour les Méthodes Non Autorisées.

exception InternalErrorException

Utilisé pour faire une Erreur 500 du Serveur Interne.

exception NotImplementedException

Utilisé pour faire une Erreur 501 Non Implémentée.

Vous pouvez lancer ces exceptions à partir de vos controllers pour indiquer les états d’échecs, ou les erreurs HTTP. Un exemple d’utilisation des exceptions HTTP pourrait être le rendu de pages 404 pour les items qui n’ont pas été trouvés:

public function view($id) {
    $post = $this->Post->findById($id);
    if (!$post) {
        throw new NotFoundException('Impossible de trouver ce poste');
    }
    $this->set('post', $post);
}

En utilisant les exceptions pour les erreurs HTTP, vous pouvez garder à la fois votre code propre, et donner les réponses complètement REST aux applications clientes et aux utilisateurs.

De plus, les exceptions de couche du framework suivantes sont disponibles, et seront lancées à partir de certains components du coeur de CakePHP:

exception CakeException

Classe d’exception de base dans CakePHP. Toutes les exceptions lancées par CakePHP étendront cette classe.

Ces classes d’exception étendent toutes CakeException. En étendant CakeException, vous pouvez créer vos propres erreurs “framework”. Toutes les Exceptions standards que CakePHP va aussi lancer les CakeException étendues.

Nouveau dans la version 2.3: CakeBaseException a été ajoutée

exception CakeBaseException

La classe d’exception de base dans CakePHP. Toutes les CakeExceptions et HttpExceptions ci-dessus étendent cette classe.

CakeBaseException::responseHeader($header = null, $value = null)

Voir CakeResponse::header().

Toutes les exceptions Http et CakePHP étendent la classe CakeBaseException, qui a une méthode pour ajouter les en-têtes à la réponse. Par exemple quand vous lancez une MethodNotAllowedException 405, le rfc2616 dit: « La réponse DOIT inclure un en-tête contenant une liste de méthodes valides pour la ressource requêtée. »

exception MissingViewException

Le fichier de vue choisi n’a pas pu être trouvé.

exception MissingLayoutException

Le layout choisi n’a pas pu être trouvé.

exception MissingHelperException

Un helper n’a pas pu être trouvé.

exception MissingBehaviorException

Un behavior configuré n’a pas pu être trouvé.

exception MissingComponentException

Un component configuré n’a pas pu être trouvé.

exception MissingTaskException

Une tâche configurée n’a pas pu être trouvée.

exception MissingShellException

La classe shell n’a pas pu être trouvée.

exception MissingShellMethodException

La classe de shell choisi n’a pas de méthode avec ce nom.

exception MissingDatabaseException

La base de donnée configurée n’existe pas.

exception MissingConnectionException

Une connexion à un model n’existe pas.

exception MissingTableException

Une table de model est manquante du cache de CakePHP ou de la source de données. Après l’ajout d’une nouvelle table à une source de données, le cache du model (trouvé dans tmp/cache/models par défaut) devra être retiré.

exception MissingActionException

L’action du controller requêté n’a pas pu être trouvé.

exception MissingControllerException

Le controller requêté n’a pas pu être trouvé.

exception PrivateActionException

Accès privé à l’action. Soit les actions ont un accès privé/protegé/préfixé par _, ou essaient d’accéder aux routes préfixés de manière incorrecte.

Utiliser les exceptions HTTP dans vos controllers

Vous pouvez envoyer n’importe quelle exception HTTP liée à partir des actions de votre controller pour indiquer les états d’échec. Par exemple:

public function view($id) {
    $post = $this->Post->findById($id);
    if (!$post) {
        throw new NotFoundException();
    }
    $this->set(compact('post'));
}

Ce qui est au-dessus causerait l”Exception.handler configurée pour attraper et traiter NotFoundException. Par défaut, cela va créer une page d’erreur et enregistrer l’exception.

Exception Renderer

class ExceptionRenderer(Exception $exception)

La classe ExceptionRenderer avec l’aide de CakeErrorController s’occupe du rendu des pages d’erreur pour toutes les exceptions lancées par votre application.

Les vues de la page d’erreur sont localisées dans app/View/Errors/. Pour toutes les erreurs 4xx et 5xx, les fichiers de vue error400.ctp et error500.ctp sont utilisées respectivement. Vous pouvez les personnaliser selon vos besoins. Par défaut, votre app/Layouts/default.ctp est utilisé aussi pour les pages d’erreur. Si par exemple, vous voulez utiliser un autre layout app/Layouts/my_error.ctp pour vos pages d’erreur, alors modifiez simplement les vues d’erreur et ajoutez le statement $this->layout = 'my_error'; à error400.ctp et error500.ctp.

Chaque exception de layer framework a son propre fichier de vue localisé dans les templates du coeur mais vous n’avez pas besoin de personnaliser les deux puisqu’ils sont utilisés seulement pendant le développement. Avec debug éteint, toutes les exceptions du layer framework sont converties en InternalErrorException.

Créer vos propres exceptions dans votre application

Vous pouvez créer vos propres exceptions d’application en utilisant toute exception SPL intégrée, Exception lui-même, ou CakeException. Les exceptions d’Application qui étendent les Exceptions ou les exceptions SPL vont être traitées comme une erreur 500 dans le mode de production. CakeException est spécial dans le fait que tous les objets CakeException sont contraints d’être soit dans des erreurs 500 soit 404, selon le code qu’ils utilisent. Quand vous êtes en mode développement, les objets CakeException ont besoin simplement d’un nouveau template qui matche le nom de classe afin fournir des informations utiles. Si votre application contenait l’exception suivante:

class MissingWidgetException extends CakeException {};

Vous pourriez fournir des erreurs de bon développement, en créant app/View/Errors/missing_widget.ctp. Quand on est en mode production, l’erreur du dessus serait traitée comme une erreur 500. Le constructeur pour CakeException a été étendu, vous autorisant à passer des données hashées. Ces hashs sont interpolés dans le messageTemplate, ainsi que dans la vue qui est utilisée pour représenter l’erreur dans le mode développement. Cela vous permet de créer des exceptions de données riches, en fournissant plus de contexte pour vos erreurs. Vous pouvez aussi fournir un template de message qui permet les méthodes natives __toString() pour fonctionner normalement:

class MissingWidgetException extends CakeException {
    protected $_messageTemplate = 'Il semblerait que %s soit manquant.';
}

throw new MissingWidgetException(array('widget' => 'Pointy'));

Quand attrapé par le gestionnaire d’exception intégré, vous obtiendriez une variable $widget dans votre template de vue d’erreur. De plus, si vous attrapez l’exception en chaîne ou utilisez sa méthode getMessage(), vous auriez Il semblerait que Pointy soit manquant.. Cela vous permet de créer facilement et rapidement vos propres erreurs de développement riche, juste comme CakePHP en interne.

Créer des codes de statut personnalisés

Vous pouvez créer des codes de statut HTTP personnalisés en changeant le code utilisé quand vous créez une exception:

throw new MissingWidgetHelperException('Widget manquant', 501);

Va créer un code de réponse 501, vous pouvez utiliser le code de statut HTTP que vous souhaitez. En développement, si votre exception n’a pas de template spécifique, et que vous utilisez un code égal ou supérieur à 500, vous verrez le template error500. Pour tout autre code d’erreur, vous aurez le template error400. Si vous avez défini un template d’erreur pour votre exception personnalisée, ce template va être utilisé en mode développement. Si vous souhaitez votre propre gestionnaire d’exception logique même en production, regardez la section suivante.

Etendre et Implementer vos Propres Gestionnaires d’Exception

Vous pouvez implémenter un gestionnaire d’exception spécifique pour votre application de plusieurs façons. Chaque approche vous donne différents montants de contrôle sur le processus de gestion d’exception.

  • Set Configure::write('Exception.handler', 'YourClass::yourMethod');

  • Create AppController::appError();

  • Set Configure::write('Exception.renderer', 'YourClass');

Dans les prochaines sections, nous allons détailler les différentes approches et les bénéfices de chacun.

Créer vos Propres Gestionnaires d’Exception avec Exception.handler

Créer votre propre gestionnaire d’exception vous donne plus de contrôle sur le processus de gestion des exceptions. La classe que vous choisissez devra être chargée dans votre app/Config/bootstrap.php, ainsi elle sera disponible pour gérer toute exception. Vous pouvez définir le gestionnaire comme tout type de callback. En configurant Exception.handler CakePHP va ignorer toutes les configurations d’Exception. Une configuration de gestionnaire d’exception personnalisée pourrait par exemple ressembler à ceci:

// dans app/Config/core.php
Configure::write('Exception.handler', 'AppExceptionHandler::handle');

// dans app/Config/bootstrap.php
App::uses('AppExceptionHandler', 'Lib');

// dans app/Lib/AppExceptionHandler.php
class AppExceptionHandler {
    public static function handle($error) {
        echo 'Oh noes! ' . $error->getMessage();
        // ...
    }
    // ...
}

Vous pouvez lancer tout code que vous souhaitez à l’intérieur de handleException. Le code ci-dessus afficherait simplement “Oh noes! “ plus le message d’exception. Vous pouvez définir des gestionnaires d’exception comme tout type de callback, même une fonction anonyme si vous utilisez PHP 5.3:

Configure::write('Exception.handler', function ($error) {
    echo 'Ruh roh ' . $error->getMessage();
});

En créant un gestionnaire d’exception personnalisé, vous pouvez fournir un gestionnaire d’erreur personnalisé pour les exceptions de l’application. Dans la méthode fournie comme un gestionnaire d’exception, vous pourriez faire comme suit:

// dans app/Lib/AppErrorHandler.php
class AppErrorHandler {
    public static function handleException($error) {
        if ($error instanceof MissingWidgetException) {
            return self::handleMissingWidget($error);
        }
        // faire d'autres trucs.
    }
}

Utiliser AppController::appError()

Implémenter cette méthode est une alternative pour implémenter un gestionnaire d’exception personnalisé. Il est fourni principalement pour une compatibilité backwards, et il n’est pas recommandé pour les nouvelles applications. Cette méthode de controller est appelée à la place du rendu d’exception par défaut. Il reçoit l’exception lancée comme son seul argument. Vous devriez implémenter votre gestionnaire d’erreur dans cette méthode:

class AppController extends Controller {
    public function appError($error) {
        // logique personnalisée va ici.
    }
}

Utiliser un rendu personnalisé avec Exception.renderer pour gérer les exceptions d’application

Si vous ne voulez pas prendre contrôle du gestionnaire d’exception, mais que vous voulez changer la façon dont les exceptions sont rendues, vous pouvez utiliser Configure::write('Exception.renderer','AppExceptionRenderer'); pour choisir une classe qui va rendre les pages d’exception. Par défaut :php:class`ExceptionRenderer` est utilisée. Votre classe de rendu d’exception personnalisée doit être placée dans app/Lib/Error. Ou un répertoire Error dans tout chemin bootstrapped Lib. Dans une classe de rendu d’exception, vous pouvez fournir une gestion spécialisée pour les erreurs spécifiques de l’application:

// dans app/Lib/Error/AppExceptionRenderer.php
App::uses('ExceptionRenderer', 'Error');

class AppExceptionRenderer extends ExceptionRenderer {
    public function missingWidget($error) {
        echo 'Oops that widget is missing!';
    }
}

Ce qui est au-dessus gérerait tout exception de type MissingWidgetException, et vous permettrait de fournir une logique d’affichage/de gestionnaire personnalisé pour ces applications. Les méthodes de gestion d’exception récupèrent l’exception en étant géré comme leur argument.

Note

Votre rendu personnalisé devrait avoir une exception comme constructeur, et implémenter une méthode de rendu. Ne pas le faire entraînera des erreurs supplémentaires.

Note

Si vous utilisez un Exception.handler personnalisé, cette configuration n’aura aucun effet. A moins que vous le référenciez à l’intérieur de votre implémentation.

Créer un controller personnalisé pour gérer les exceptions

Dans votre sous-classe ExceptionRenderer, vous pouvez utiliser la méthode _getController pour vous permettre de retourner un controller personnalisé pour gérer vos erreurs/ Par défaut, CakePHP utilise CakeErrorController qui enlève quelques callbacks habituels pour aider à s’assurer que les erreurs s’affichent toujours. Cependant, vous aurez peut-être besoin d’un controller de gestionnaire d’erreur plus personnalisé dans votre application. En implémentant _getController dans votre classe AppExceptionRenderer, vous pouvez utiliser tout controller que vous souhaitez:

class AppExceptionRenderer extends ExceptionRenderer {
    protected function _getController($exception) {
        App::uses('SuperCustomErrorController', 'Controller');
        return new SuperCustomErrorController();
    }
}

De façon alternative, vous pouvez simplement écraser le CakeErrorController du coeur, en en incluant un dans app/Controller. Si vous utilisez un controller personnalisé pour la gestion des erreurs, assurez-vous de faire toutes les configurations dont vous aurez besoin dans votre constructeur, ou dans la méthode de rendu. Puisque celles-ci sont les seules méthodes que la classe ErrorHandler intégrée appelle directement.

Logging Exceptions

Utiliser la gestion d’exception intégrée, vous pouvez lancer les exceptions qui sont gérées avec ErrorHandler en configurant Exception.log à true dans votre core.php. Activer cela va lacer chaque exception vers CakeLog et les loggers configurés.

Note

Si vous utilisez un Exception.handler personnalisé, cette configuration n’aura aucun effet. A moins que vous le référenciez à l’intérieur de votre implémentation.