37 votes

Consignation des erreurs, en douceur

J'ai lu des articles sur l'enregistrement des erreurs et j'ai trouvé la fonction 'error_log' qui semble être un bon outil pour gérer l'enregistrement des erreurs. Mais quelle est la meilleure façon de l'utiliser ?

Si j'ai un

try {
     //try a database connection...

} catch (PDOException $e) {
    error_log($e->getMessage(), 3, "/var/tmp/my-errors.log");

}

L'erreur est alors enregistrée dans le fichier my-errors.log. Mais qu'en est-il si j'ai parfois besoin de modifier la position du fichier, de changer de dossier ou autre chose. Si j'ai des tonnes de fichiers, je dois tous les modifier.

Maintenant, j'ai commencé à penser à utiliser une variable pour définir le chemin vers le journal des erreurs. Bien sûr, cela pourrait fonctionner, mais que faire si je veux utiliser le journal des erreurs dans une fonction ou une méthode de classe ? Alors je devrais définir la variable comme globale, mais c'est considéré comme une mauvaise pratique ! Mais que faire si je ne dois pas utiliser la fonction en profondeur dans une classe, ne serait-ce pas également une mauvaise pratique ? Quelle est la bonne solution dans ce cas ?

<?php

function legit() {
    try {
        if (1 == 1) {
            throw new Exception('There was an error here');
        }
    } catch (Exception $e) {
        throw new Exception('throw the error to the try-catch outside the function...');
    }

}

try {
    legit();
} catch (Exception $e) {
    echo 'error here' . $e->getMessage();

    //log it
}

Ceci est un exemple de ce dont je parlais plus haut (Ne pas avoir la journalisation au plus profond d'une classe/fonction... Est-ce une bonne façon de faire ?)

Plus loin :

Je ne suis pas tout à fait sûr de la façon dont je dois utiliser les exceptions en général. Disons que je veux faire un INSERT dans une base de données avec du SQL à l'intérieur d'une méthode, dois-je utiliser un try/catch et relancer l'exception si elle échoue ? Est-ce considéré comme une bonne pratique ? Veuillez nous donner des exemples.

0 votes

Avez-vous envisagé d'utiliser l'enregistrement d'erreurs intégré, en utilisant la commande log_errors et, facultativement, la directive de configuration trigger_error pour les envoyer dans les journaux ? Cela les envoie dans les journaux d'erreurs de votre serveur web. Et vous n'avez pas à le faire manuellement.

2 votes

Eh bien, selon le cas, j'aimerais utiliser différentes méthodes de consignation, courriel, base de données, etc.

87voto

Paul Points 2497

Tout d'abord, je vous félicite d'avoir étudié les méthodes d'erreur standard de PHP. Malheureusement, error_log a quelques limites comme vous l'avez découvert.

C'est une longue réponse, lisez la suite pour en savoir plus :

  1. Erreurs
    • Enregistrer directement l'erreur par rapport à trigger_error y set_error_handler
    • Quand les bonnes erreurs tournent mal - Erreurs fatales.
  2. Exceptions
    • SPL
    • Que faire d'eux ?
  3. Code
    • Configuration
    • Utilisation

TL;DR Utilisez trigger_error pour signaler les erreurs et set_error_handler pour les enregistrer.

1. Erreurs

Lorsque les choses ne se passent pas comme prévu dans votre programme, vous voudrez souvent déclencher une erreur afin que quelqu'un ou quelque chose en soit informé. Une erreur correspond à une situation où le programme peut continuer, mais où quelque chose de notable, éventuellement nuisible ou erroné, s'est produit. À ce stade, de nombreuses personnes souhaitent enregistrer immédiatement l'erreur avec le logiciel d'enregistrement de leur choix. Je pense que c'est exactement la mauvaise chose à faire. Je recommande d'utiliser trigger_error pour soulever l'erreur afin qu'elle puisse être gérée par un callback défini par set_error_handler . Comparons ces options :

Enregistrement direct de l'erreur

Vous avez donc choisi votre forfait d'exploitation forestière. Vous êtes maintenant prêt à diffuser les appels à votre logger partout où une erreur se produit dans votre code. Examinons un appel unique que vous pourriez faire (j'utiliserai un logger similaire à celui de la réponse de Jack) :

Logger::getLogger('standard')->error('Ouch, this hurts');

Que faut-il mettre en place pour exécuter ce code ?

    **Class**:  Logger
    **Method**: getLogger
    **Return**: Object with method 'error'

Ce sont les dépendances nécessaires pour utiliser ce code. Tous ceux qui veulent réutiliser ce code devront fournir ces dépendances. Cela signifie qu'une configuration PHP standard ne sera plus suffisante pour réutiliser votre code. Dans le meilleur des cas, en utilisant l'injection de dépendances, vous avez toujours besoin d'un objet logger à passer dans tout votre code qui peut émettre une erreur.

De plus, en plus de ce dont le code est responsable, il est également responsable de l'enregistrement de l'erreur. Cela va à l'encontre de la Principe de responsabilité unique .

On peut voir que l'enregistrement direct de l'erreur est mauvais .

trigger_error à la rescousse

PHP possède une fonction appelée trigger_error qui peut être utilisé pour lever une erreur comme le font les fonctions standard. Les niveaux d'erreur que vous utilisez avec cette fonction sont définis dans le champ constantes de niveau d'erreur . En tant qu'utilisateur, vous devez utiliser l'une des erreurs d'utilisateur : E_USER_ERROR , E_USER_WARNING ou la valeur par défaut E_USER_NOTICE (les autres niveaux d'erreur sont réservés aux fonctions standard, etc.) L'utilisation d'une fonction PHP standard pour générer l'erreur permet de réutiliser le code avec n'importe quelle installation PHP standard ! Notre code n'est plus responsable de l'enregistrement de l'erreur (il s'assure seulement qu'elle est levée).

Utilisation de trigger_error nous n'effectuons que la moitié du processus d'enregistrement des erreurs (soulever l'erreur) et nous réservons la responsabilité de la réponse à l'erreur au gestionnaire d'erreurs, qui sera abordé plus loin.

Gestionnaire d'erreurs

Nous avons défini un gestionnaire d'erreurs personnalisé avec l'option set_error_handler (voir la configuration du code). Ce gestionnaire d'erreurs personnalisé remplace le gestionnaire d'erreurs standard de PHP qui enregistre normalement les messages dans le journal d'erreurs du serveur Web en fonction des paramètres de configuration de PHP. Nous pouvons toujours utiliser ce gestionnaire d'erreur standard en retournant la fonction false dans notre gestionnaire d'erreurs personnalisé.

Le gestionnaire d'erreurs personnalisé n'a qu'une seule responsabilité : répondre à l'erreur (y compris la journalisation que vous souhaitez effectuer). Dans le gestionnaire d'erreur personnalisé, vous avez un accès complet au système et vous pouvez exécuter n'importe quel type de journalisation que vous voulez. Pratiquement n'importe quel logger qui utilise le modèle de conception Observer fera l'affaire (je ne vais pas m'étendre sur ce sujet car je pense qu'il est d'une importance secondaire). Cela devrait vous permettre d'accrocher de nouveaux observateurs de logs pour envoyer la sortie là où vous en avez besoin.

Vous avez le contrôle total pour faire ce que vous voulez avec les erreurs dans une seule partie maintenable de votre code. L'enregistrement des erreurs peut désormais être modifié rapidement et facilement d'un projet à l'autre ou d'une page à l'autre au sein d'un même projet. Il est intéressant de noter que même @ Les erreurs supprimées sont transmises au gestionnaire d'erreurs personnalisé avec un message errno de 0 qui, si le error_reporting masque est respecté ne doit pas être signalé.

Quand les bonnes erreurs tournent mal - les erreurs fatales

Il n'est pas possible de poursuivre à partir de certaines erreurs. Les niveaux d'erreur suivants ne peuvent pas être traités par un gestionnaire d'erreurs personnalisé : E_ERROR , E_PARSE , E_CORE_ERROR , E_CORE_WARNING , E_COMPILE_ERROR , E_COMPILE_WARNING . Lorsque ce type d'erreur est déclenché par un appel de fonction standard, le gestionnaire d'erreur personnalisé est ignoré et le système s'arrête. Ceci peut être généré par :

call_this_function_that_obviously_does_not_exist_or_was_misspelt();

Il s'agit d'un sérieux erreur ! Il est impossible de s'en remettre, et le système est sur le point de s'arrêter. Notre seul choix est d'avoir register_shutdown_function de faire face au shutdown. Cependant, cette fonction est exécutée chaque fois qu'un script se termine (avec succès, ainsi qu'en cas d'échec). En utilisant cette fonction et error_get_last quelques informations de base peuvent être enregistrées (le système est presque arrêté à ce stade) lorsque la dernière erreur était une erreur fatale. Il peut également être utile d'envoyer le code d'état correct et d'afficher une page de type Internal Server Error de votre choix.

2. Exceptions

Les exceptions peuvent être traitées de manière très similaire aux erreurs de base. Au lieu de trigger_error une exception sera levée par votre code (manuellement avec throw new Exception ou à partir d'un appel de fonction standard). Utilisez set_exception_handler pour définir le callback que vous voulez utiliser pour gérer l'exception.

SPL

La bibliothèque standard de PHP (SPL) fournit exceptions . C'est ma façon préférée de soulever des exceptions parce que comme trigger_error ils sont une partie standard de PHP qui n'introduit pas de dépendances supplémentaires dans votre code.

Que faire d'eux ?

Lorsqu'une exception est levée, trois choix s'offrent à vous :

  1. Attrapez-le et réparez-le (le code continue ensuite comme si de rien n'était).
  2. Attrapez-le, ajoutez-y des informations utiles et rejetez-le.
  3. Laissez-le s'élever à un niveau supérieur.

Ces choix sont faits à chaque niveau de la pile. Finalement, une fois que la pile atteint le niveau le plus élevé, le callback que vous avez défini avec la commande set_exception_handler sera exécuté. C'est ici qu'il faut placer le code de journalisation (pour les mêmes raisons que la gestion des erreurs) plutôt que de l'éparpiller dans tout le système. catch dans votre code.

3. Code

Configuration

Gestionnaire d'erreurs

function errorHandler($errno , $errstr, $errfile, $errline, $errcontext)
{
    // Perform your error handling here, respecting error_reporting() and
    // $errno.  This is where you can log the errors.  The choice of logger
    // that you use is based on your preference.  So long as it implements
    // the observer pattern you will be able to easily add logging for any
    // type of output you desire.
}

$previousErrorHandler = set_error_handler('errorHandler');

Gestionnaire d'exceptions

function exceptionHandler($e)
{
    // Perform your exception handling here.
}

$previousExceptionHandler = set_exception_handler('exceptionHandler');

Fonction d'arrêt

function shutdownFunction()
{
    $err = error_get_last();

    if (!isset($err))
    {
        return;
    }

    $handledErrorTypes = array(
        E_USER_ERROR      => 'USER ERROR',
        E_ERROR           => 'ERROR',
        E_PARSE           => 'PARSE',
        E_CORE_ERROR      => 'CORE_ERROR',
        E_CORE_WARNING    => 'CORE_WARNING',
        E_COMPILE_ERROR   => 'COMPILE_ERROR',
        E_COMPILE_WARNING => 'COMPILE_WARNING');

    // If our last error wasn't fatal then this must be a normal shutdown.  
    if (!isset($handledErrorTypes[$err['type']]))
    {
        return;
    }

    if (!headers_sent())
    {
        header('HTTP/1.1 500 Internal Server Error');
    }

    // Perform simple logging here.
}

register_shutdown_function('shutdownFunction');

Utilisation

Erreurs

// Notices.
trigger_error('Disk space is below 20%.', E_USER_NOTICE);
trigger_error('Disk space is below 20%.'); // Defaults to E_USER_NOTICE

// Warnings.
fopen('BAD_ARGS'); // E_WARNING fopen() expects at least 2 parameters, 1 given
trigger_error('Warning, this mode could be dangerous', E_USER_WARNING);

// Fatal Errors.    
// This function has not been defined and so a fatal error is generated that
// does not reach the custom error handler.
this_function_has_not_been_defined();
// Execution does not reach this point.

// The following will be received by the custom error handler but is fatal.
trigger_error('Error in the code, cannot continue.', E_USER_ERROR);
// Execution does not reach this point.

Exceptions

Chacun des trois choix précédents est énuméré ici de manière générique, le fixer, le compléter et le laisser bouillonner.

1 Fixable :

try
{
    $value = code_that_can_generate_exception();
}
catch (Exception $e)
{
    // We decide to emit a notice here (a warning could also be used).
    trigger_error('We had to use the default value instead of ' .
                  'code_that_can_generate_exception\'s', E_USER_NOTICE);
    // Fix the exception.
    $value = DEFAULT_VALUE;
}

// Code continues executing happily here.

2 Appendice :

Observez ci-dessous comment le code_that_can_generate_exception() n'est pas au courant $context . Le bloc catch à ce niveau dispose de plus d'informations qu'il peut ajouter à l'exception si cela est utile en la rejetant à nouveau.

try
{
    $context = 'foo';
    $value = code_that_can_generate_exception();
}
catch (Exception $e)
{
    // Raise another exception, with extra information and the existing
    // exception set as the previous exception. 
    throw new Exception('Context: ' . $context, 0, $e);
}

3 Laissez-le bouillonner :

// Don't catch it.

0 votes

Merci pour ce très bon article, j'ai en fait trouvé le set_error_handler il y a un certain temps, mais cela a rendu le sujet plus clair. En ce qui concerne les exceptions, comment faites-vous ? Dois-je attraper les erreurs dans toutes les méthodes d'une classe ou laisser le set_exception_handler de plus haut niveau s'en charger ? :)

1 votes

Je ne l'attrape que lorsque je peux faire quelque chose d'utile. Vous reconnaîtrez le niveau où vous pouvez faire quelque chose d'utile quand vous le verrez. Si vous avez un doute, laissez-le s'exprimer. Le gestionnaire d'exception set ne sera pas capable de réparer une exception, mais peut être approprié pour les exceptions avec lesquelles votre code ne peut tout simplement pas fonctionner. Par exemple : Je m'attendrais à ce que la base de données lance des exceptions et que les méthodes qui utilisent la base de données les attrapent (à l'exception peut-être d'un échec de connexion à la base de données qui pourrait être géré par le gestionnaire d'exception set_exception_handler). Mais cela dépend vraiment de chaque situation.

0 votes

Bien que cette réponse ait été écrite en 2012, je l'ai encore trouvée très utile. Merci beaucoup de l'avoir rendu très clair @paul

36voto

Jack Points 88446

Il a été demandé de rendre cette réponse plus applicable à un public plus large, alors voici.

Preámbulo

La gestion des erreurs n'est généralement pas la première chose à laquelle vous souhaitez penser lorsque vous écrivez une application ; elle est donc indirectement ajoutée lorsque le besoin s'en fait sentir. Cependant, cela ne doit pas coûter cher d'utiliser les mécanismes existants en PHP.

C'est un article assez long, c'est pourquoi je l'ai divisé en plusieurs parties logiques.

Déclenchement d'erreurs

En PHP, il existe deux façons distinctes de déclencher des erreurs :

  1. Des erreurs provenant de PHP lui-même (par exemple, l'utilisation de variables non définies) ou de fonctions internes (par exemple, l'utilisation d'un mot de passe). imagecreatefromjpeg n'a pas pu ouvrir un fichier),
  2. Erreurs déclenchées par le code utilisateur utilisant trigger_error ,

Ils sont généralement imprimés sur votre page (sauf si display_errors est éteint ou error_reporting est zéro), ce qui devrait être la norme pour les machines de production, à moins que vous n'écriviez du code parfait comme moi ... passons) ; ces erreurs peuvent également être capturées, vous donnant un aperçu de tout problème dans le code, en utilisant set_error_handler expliqué plus tard.

Lancer des exceptions

Les exceptions se distinguent des erreurs de trois manières principales :

  1. Le code qui les traite peut être très éloigné de l'endroit d'où ils sont lancés. L'état de la variable à l'origine doit être explicitement passé au constructeur de l'exception, sinon vous n'avez que la trace de la pile.
  2. Le code entre l'exception et le catch est entièrement sauté, alors qu'après une erreur (et elle n'était pas fatale) le code continue.
  3. Ils peuvent être prolongés à partir de l'unité principale Exception Cela vous permet d'attraper et de traiter des exceptions spécifiques, mais de laisser les autres descendre dans la pile jusqu'à ce qu'elles soient attrapées par un autre code. Voir aussi : http://www.php.net/manual/en/language.exceptions.php

Un exemple de lancement d'exceptions est donné plus loin.

Traitement des erreurs

La capture et la gestion des erreurs sont assez simples en enregistrant un gestionnaire d'erreurs, par exemple :

function my_error_handler($errno, $errstr, $errfile = 'unknown', $errline = 0, array $errcontext = array())
{
    // $errcontext is very powerful, it gives you the variable state at the point of error; this can be a pretty big variable in certain cases, but it may be extremely valuable for debugging
    // if error_reporting() returns 0, it means the error control operator was used (@)
    printf("%s [%d] occurred in %s:%d\n%s\n", $errstr, $errno, $errfile, $errline, print_r($errcontext, true));

    // if necessary, you can retrieve the stack trace that led up to the error by calling debug_backtrace()

    // if you return false here, the standard PHP error reporting is performed
}

set_error_handler('my_error_handler');

Pour le plaisir, vous pouvez transformer toutes les erreurs en un fichier de type ErrorException en enregistrant le gestionnaire d'erreurs suivant (PHP >= 5.1) :

function exception_error_handler($errno, $errstr, $errfile, $errline)
{
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}

set_error_handler("exception_error_handler");

Traitement des exceptions

Dans la plupart des cas, vous traitez les exceptions aussi près que possible du code qui les a provoquées afin de permettre des plans de sauvegarde. Par exemple, vous tentez d'insérer un enregistrement dans une base de données et une exception de contrainte de clé primaire est levée ; vous pouvez récupérer en mettant à jour l'enregistrement à la place (artificiel car la plupart des bases de données peuvent gérer cela elles-mêmes). Certaines exceptions ne peuvent tout simplement pas être gérées localement, et vous souhaitez donc qu'elles soient répercutées en cascade. Exemple :

function insertRecord($user, $name)
{
    try {
        if (true) {
            throw new Exception('This exception should not be handled here');
        }
        // this code is not executed
        $this->db->insert('users', array('uid' => $user, 'name' => $name));
    } catch (PDOException $e) {
        // attempt to fix; an exception thrown here will cascade down
        throw $e; // rethrow exception

        // since PHP 5.3.0 you can also nest exceptions
        throw new Exception("Could not insert '$name'", -1, $e);
    } catch (WhatEverException $e) {
        // guess what, we can handle whatever too
    }
}

L'exception glissante

Que se passe-t-il si vous n'attrapez pas une exception quelque part ? Vous pouvez aussi l'attraper en utilisant set_exception_handler .

function my_exception_handler(Exception $exception)
{
    // do your stuff here, just don't throw another exception here
}

set_exception_handler('my_exception_handler');

Ceci n'est pas encouragé, à moins que vous n'ayez aucun moyen significatif de gérer l'exception dans votre code.

Consignation de l'erreur/exception

Maintenant que vous avez traité l'erreur, vous devez l'enregistrer quelque part. Pour mon exemple, j'utilise un projet qu'Apache a porté de Java à PHP, appelé LOG4PHP . Il y en a d'autres, mais cela illustre l'importance d'une installation d'enregistrement flexible.

Il utilise les concepts suivants :

  1. Enregistreurs - entités nommées qui effectuent la journalisation en votre nom ; elles peuvent être spécifiques à une classe de votre projet ou partagées en tant que logger commun,
  2. Appendices - chaque demande de journal peut être envoyée à une ou plusieurs destinations (courriel, base de données, fichier texte) en fonction de conditions prédéfinies (comme le niveau du journal),
  3. Niveaux - les journaux sont classés des messages de débogage aux erreurs fatales.

Utilisation de base pour illustrer les différents niveaux de message :

Logger::getLogger('main')->info('We have lift off');
Logger::getLogger('main')->warn('Rocket is a bit hot');
Logger::getLogger('main')->error('Houston, we have a problem');

En utilisant ces concepts, vous pouvez modéliser une installation de journalisation assez puissante ; par exemple, sans modifier le code ci-dessus, vous pouvez mettre en œuvre la configuration suivante :

  1. Collecte de tous les messages de débogage dans une base de données pour que les développeurs puissent les consulter ; vous pouvez désactiver cette fonction sur le serveur de production,
  2. Rassemblez les avertissements dans un fichier quotidien que vous pourriez envoyer par courriel à la fin de la journée,
  3. Faites envoyer des courriels immédiats en cas d'erreurs fatales.

4 votes

Hahaha, belle référence à Houston :P

0 votes

@Jack réponse très complète. sur le même sujet de la gestion des erreurs (bien qu'en c++) vous avez fermé l'une de mes questions comme étant "vague", sans l'aide ou la courtoisie d'une explication ou d'une indication sur la façon de la rendre moins offensante pour vous et les vôtres. je l'ai éditée et demande votre soutien pour la revoir (si vous la fermez, vous devriez être le premier à analyser si elle est MAINTENANT ok). j'apprécierais grandement votre soutien. ps : produit très cool votre muvee, je vous contacterai à ce sujet dans un avenir proche ! stackoverflow.com/questions/12609104/catch-mysql-error-in-c

3voto

Tom van der Woerdt Points 18645

Définissez-le, puis utilisez-le :)

define('ERRORLOG_PATH', '/var/tmp/my-errors.log');

error_log($e->getMessage(), 3, ERRORLOG_PATH);

Alternativement, il suffit de faire du troisième paramètre de error_log facultatif, en le mettant par défaut sur le chemin que vous voulez.

3voto

Alexey Points 840

Si vous avez toujours besoin d'une manière personnalisée de gérer les journaux (c'est-à-dire que vous ne voulez pas utiliser le standard trigger_error() ), je recommande de regarder Zend_Log ( http://framework.zend.com/manual/en/zend.log.overview.html ) pour ces raisons :

  1. il peut être utilisé comme un composant autonome, ZF n'est pas un framework complet. Vous pouvez copier seulement les espaces de noms Zend_Loader et Zend_Log, instancier Zend_Loader et l'utiliser. Voir ci-dessous :

    require_once('Zend/Loader/Autoloader.php');
    
    $loader = Zend_Loader_Autoloader::getInstance();
    
    $logger = new Zend_Log();    
    $writer = new Zend_Log_Writer_Stream('php://output');
    
    $logger->addWriter($writer);    
    $logger->log('Informational message', Zend_Log::INFO);
  2. On vous a proposé de nombreuses bibliothèques de journalisation, mais je pense que l'équipe de Zend (fondateurs de PHP lang) sait ce qu'elle fait.

  3. Vous pouvez utiliser n'importe quel rédacteur (base de données, STDOUT - voir ci-dessus, fichier, n'importe quoi, vous pouvez le personnaliser pour écrire le vôtre afin d'envoyer des messages de journal à un service Web).

  4. niveaux de journal

  5. peut changer le format du journal (mais celui qui est prêt à l'emploi est excellent à mon avis). L'exemple ci-dessus avec le formateur standard produira quelque chose comme ceci :

2012-05-07T23:57:23+03:00 INFO (6) : Message d'information

  1. lisez juste la référence, il peut être configuré pour attraper les erreurs php

0 votes

J'ai utilisé le Zend_log dans d'autres projets, et pour une raison quelconque, je n'étais pas vraiment satisfait, mais merci quand même pour votre réponse.

0 votes

@John : il y a aussi monologue y apache log4php - c'est probablement utile.

3voto

sakfa Points 1587

En outre, pour la journalisation des erreurs (et en fait pour toute la journalisation), j'utiliserais un distributeur d'événements, comme le fait le framework Symfony.

Jetez un coup d'œil à ce composant sf (il s'agit d'une dépendance très légère, le framework entier n'est pas nécessaire, il y a peut-être 3 classes php pertinentes et 2 interfaces).

https://github.com/symfony/EventDispatcher

de cette façon, vous pouvez créer un distributeur quelque part dans le bootstrap de votre application :

use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;

$dispatcher = new EventDispatcher();

//register listeners
$dispatcher->addListener('application.log', function (Event $event) {
    //do anything you want
});

Ensuite, vous pouvez déclencher un événement à n'importe quel endroit de votre code par quelque chose comme

$dispatcher->dispatch(new GenericEvent('application.log', array('message' => 'some log', 'priority' => 'high'));

Bien sûr, vous pouvez sous-classer la classe d'événements avec vos propres événements :

class LogEvent extends GenericEvent {
    public function __construct($message, $priority = 'INFO') {
        parent::__construct('application.log', array('message'=>$message,'priority'=>$priority));
    }
    public function getMessage() { return $this->getArgument('message'); }
    public function getPriority() { return $this->getArgument('priority'); }
}

// now raising LogEvent is much cleaner:
$dispatcher->dispatch(new LogEvent('some log'));

Cela vous permettra également de créer des événements plus personnalisés comme ExceptionEvent

 class ExceptionEvent extends GenericEvent {
    public function __construct(Exception $cause) {
        parent::__construct('exception.event', array('cause' => $cause));
    }
 }

Et traitez-les en conséquence.

Avantages

  • vous séparez la logique de journalisation de votre application
  • vous pouvez facilement ajouter et supprimer des enregistreurs en cours d'exécution
  • vous pouvez facilement enregistrer autant de loggers que vous le souhaitez (c'est-à-dire DebugLogger qui enregistre tout dans un fichier texte, ErrorLogger qui enregistre uniquement les erreurs dans error_log, CriticalLogger qui enregistre uniquement les erreurs critiques sur l'environnement de production et les envoie par e-mail à l'administrateur, etc.)
  • vous pouvez utiliser le distributeur d'événements pour d'autres choses que la journalisation (en fait pour chaque tâche pour laquelle le modèle d'observateur est approprié)
  • Le logger actuel ne devient rien de plus qu'un "détail d'implémentation" - il est si facile à remplacer que l'endroit où vont vos logs n'a pas d'importance - vous pourrez remplacer la destination des logs à tout moment sans avoir à remanier les noms de vos méthodes, ou à changer quoi que ce soit dans le code.
  • il sera facile de mettre en œuvre une logique complexe de routage des journaux ou de changer globalement le format des journaux (en configurant les enregistreurs)
  • tout devient encore plus flexible si vous utilisez l'injection de dépendances à la fois pour les listeners (loggers) et les dispatcher (dans les classes qui notifient les événements de logs)

Enregistrement réel

Comme quelqu'un l'a déjà dit, je conseillerais d'utiliser une bibliothèque prête à l'emploi, comme Monolog, Zend_Log ou log4php, il n'y a probablement aucune raison de coder ces choses à la main (et la dernière chose que vous voulez est un logger d'erreur cassé !)

PS : Traitez les extraits de code comme un pseudo-code, je ne les ai pas testés. Les détails peuvent être trouvés dans les docs des bibliothèques mentionnées.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X