Registrazione degli errori, in modo uniforms

Ho letto in particolare 'error logging' e ho trovato la function 'error_log' che sembra essere un buon strumento da usare per gestire la logging degli errori. Ma come è il modo più fluido e migliore per usarlo?

Se ho un

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

Ciò registrerebbe l'errore nel file my-errors.log. Ma cosa succede se a volte ho bisogno di cambiare la posizione di where si trova il file, una nuova cartella o qualcosa del genere. Se ho un sacco di file ho bisogno di cambiarli tutti.

Ora ho iniziato a pensare di usare una variabile per impostare il path del log degli errori. Certo che potrebbe funzionare, ma cosa succede se voglio usare error_log in un metodo di function o di class? Quindi avrei bisogno di impostare la variabile come globale, ma questa è considerata una ctriggers pratica! Ma cosa succede se non wheressi usare la function in profondità in una class, non sarebbe considerata una ctriggers pratica? Qual è una buona soluzione qui?

 <?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 } 

Questo è un esempio di ciò di cui stavo parlando sopra (non avendo il logging in profondità in una class / function … è un buon modo?)

Più avanti:

Non sono abbastanza sicuro di come dovrei usare le eccezioni in generale. Diciamo che voglio fare un INSERT in un database con SQL all'interno di un metodo, dovrei usare un try / catch e quindi rilanciare l'exception se fallisce? È considerata una buona pratica? Esempi per favore.

Innanzitutto, vorrei raccomandarti per aver guardato i methods di errore standard all'interno di PHP. Sfortunatamente error_log ha alcune limitazioni come hai scoperto.

Questa è una lunga risposta, continua a leggere per scoprire:

  1. Errori
    • Registrazione dell'errore direttamente vs trigger_error e trigger_error
    • Dove errori buoni vanno male – Errori fatali.
  2. eccezioni
    • SPL
    • cosa fare con loro?
  3. Codice
    • Impostare
    • uso

TL; DR Usa trigger_error per generare errori e set_error_handler per registrarli.

1. Errori

Quando le cose non vanno come previsto nel tuo programma, spesso vuoi segnalare un errore in modo che qualcuno o qualcosa venga notificato. Un errore riguarda una situazione in cui il programma potrebbe continuare, ma si è verificato qualcosa di notevole, probabilmente dannoso o errato. A questo punto molte persone vogliono registrare immediatamente l'errore con il loro pacchetto di logging preferito. Credo che questa sia esattamente la cosa sbagliata da fare. Raccommand di utilizzare trigger_error per generare l'errore in modo che possa essere gestito con un callback impostato da set_error_handler . Consente di confrontare queste opzioni:

Registrazione dell'errore direttamente

Quindi, hai scelto il tuo pacchetto di logging. Ora sei pronto per diffondere le chiamate al tuo registratore ovunque si verifichi un errore nel tuo codice. Vediamo una singola chiamata che potresti fare (userò un logger simile a quello nella risposta di Jack):

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

Cosa ti serve per eseguire questo codice?

     Classe : Logger
     Metodo : getLogger
     Ritorno : object con metodo 'errore'

Queste sono le dependencies necessarie per utilizzare questo codice. Chiunque voglia riutilizzare questo codice dovrà fornire queste dependencies. Ciò significa che una configuration PHP standard non sarà più sufficiente per riutilizzare il tuo codice. Con il migliore dei casi, utilizzando Dependency Injection è ancora necessario che un object logger venga passato in tutto il codice in grado di emettere un errore.

Inoltre, oltre a qualunque sia il codice responsabile, ha anche la responsabilità di registrare l'errore. Ciò va contro il principio di responsabilità unica .

Possiamo vedere che registrare l'errore direttamente è sbagliato .

trigger_error per il salvataggio

PHP ha una function chiamata trigger_error che può essere utilizzata per generare un errore proprio come fanno le funzioni standard. I livelli di errore che si utilizzano con esso sono definiti nelle costanti del livello di errore . Come utente è necessario utilizzare uno degli errori utente: E_USER_ERROR , E_USER_WARNING o il valore predefinito E_USER_NOTICE (altri livelli di errore sono riservati per le funzioni standard ecc.). L'utilizzo di una function PHP standard per aumentare l'errore consente di riutilizzare il codice con qualsiasi installazione PHP standard! Il nostro codice non è più responsabile per la logging dell'errore (solo assicurandosi che sia stato generato).

Usando trigger_error eseguiamo solo metà del process di logging degli errori (innalzando l'errore) e salviamo la responsabilità di rispondere all'errore per il gestore degli errori che verrà trattato successivamente.

Gestore degli errori

Impostiamo un gestore di errori personalizzato con la function set_error_handler (vedi l'impostazione del codice). Questo gestore di errori personalizzato sostituisce il gestore di errori PHP standard che normalmente registra i messaggi nel log degli errori del server Web in base alle impostazioni di configuration di PHP. Possiamo ancora usare questo gestore di errori standard restituendo false all'interno del nostro gestore di errori personalizzato.

Il gestore di errori personalizzato ha una sola responsabilità: rispondere all'errore (incluso qualsiasi logging che si desidera eseguire). All'interno del gestore di errori personalizzato hai pieno accesso al sistema e puoi eseguire qualsiasi tipo di logging che desideri. Praticamente qualsiasi logger che utilizza il model di progettazione di Observer sarà ok (non ho intenzione di entrare in quello che ritengo sia di secondaria importnza). Questo dovrebbe consentire di colbind nuovi osservatori di log per submit l'output where necessario.

Hai il controllo completo di fare ciò che ti piace con gli errori in un'unica parte del tuo codice gestibile. La logging degli errori può ora essere modificata rapidamente e facilmente da un progetto all'altro o all'interno di un singolo progetto da una pagina all'altra. È interessante notare che anche gli errori @ soppressi lo rendono al gestore di errori personalizzato con un errno di 0 che, se la maschera error_reporting viene rispettata, non dovrebbe essere segnalata.

Quando i buoni errori vanno male – Errori fatali

Non è ansible continuare da determinati errori. I seguenti livelli di errore non possono essere gestiti da un gestore di errori personalizzato: E_ERROR , E_PARSE , E_CORE_ERROR , E_CORE_WARNING , E_COMPILE_ERROR , E_COMPILE_WARNING . Quando questi tipi di errori vengono triggersti ​​da una chiamata di function standard, il gestore di errori personalizzato viene saltato e il sistema si arresta. Questo può essere generato da:

call_this_function_that_obviously_does_not_exist_or_was_misspelt();

Questo è un grave errore! È imansible da recuperare e il sistema sta per spegnersi. La nostra unica scelta è avere un accordo register_shutdown_function con l'arresto. Tuttavia questa function viene eseguita each volta che uno script viene completato (con esito positivo, oltre che non riuscito). Usando questo e error_get_last possono essere registrate alcune informazioni di base (il sistema è quasi inattivo a questo punto) quando l'ultimo errore è stato un errore fatale. Può anche essere utile submit il codice di stato corretto e mostrare una pagina di tipo Errore interno del server di tua scelta.

2. Eccezioni

Le eccezioni possono essere trattate in modo molto simile agli errori di base. Invece di trigger_error verrà generata un'exception dal codice (manualmente con la throw new Exception o da una chiamata di function standard). Utilizzare set_exception_handler per definire il callback che si desidera utilizzare per gestire l'exception con.

SPL

La libreria PHP standard (SPL) fornisce eccezioni . Sono il mio modo preferito di sollevare eccezioni perché come trigger_error sono una parte standard di PHP che non introduce dependencies extra al tuo codice.

cosa fare con loro?

Quando viene lanciata un'exception, ci sono tre scelte che possono essere fatte:

  1. Catturalo e risolvilo (il codice continua come se non fosse successo niente).
  2. Catturalo, aggiungi informazioni utili e rilancia.
  3. Lascia che bolla fino a un livello più alto.

Ad each livello dello stack vengono fatte queste scelte. Alla fine, una volta raggiunto il livello più alto, verrà eseguita la richiamata impostata con set_exception_handler . Questo è il punto in cui il tuo codice di logging appartiene (per gli stessi motivi della gestione degli errori) piuttosto che diffuso in tutte le dichiarazioni catch del tuo codice.

3. Codice

Impostare

Gestore degli errori

 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'); 

Gestore di eccezioni

 function exceptionHandler($e) { // Perform your exception handling here. } $previousExceptionHandler = set_exception_handler('exceptionHandler'); 

Funzione di spegnimento

 function shutdownFunction() { $err = error_get_last(); if (!isset($err)) { return; } $handledErrorTypes = arrays( 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'); 

uso

Errori

 // 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. 

eccezioni

Ognuna delle tre scelte precedenti è elencata qui in modo generico, risolvendola, aggiungendola e facendola esplodere.

1 riparabile:

 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 Aggiungi:

Osserva di seguito come il code_that_can_generate_exception() non conosce il $context . Il block catch a questo livello ha più informazioni che può aggiungere all'exception se è utile rilanciandolo.

 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 Lascia che bolla:

 // Don't catch it. 

È stato chiesto di rendere questa risposta più applicabile a un pubblico più ampio, quindi ecco qui.

Preambolo

La gestione degli errori di solito non è la prima cosa a cui vornetworking pensare quando scrivete un'applicazione; come risultato indiretto si imballa a seconda delle necessità. Tuttavia, non deve costare molto per sfruttare i meccanismi esistenti in PHP.

È un articolo abbastanza lungo, quindi l'ho suddiviso in serie logiche di text.

Errori di trigger

All'interno di PHP ci sono due modi distinti per l'triggerszione degli errori:

  1. Errori da PHP stesso (es. Utilizzo di variables non definite) o funzioni interne (es. imagecreatefromjpeg non può aprire un file),
  2. Errori triggersti ​​dal codice utente utilizzando trigger_error ,

Questi sono solitamente printingti sulla tua pagina (a less che display_errors sia spento o error_reporting sia zero), che dovrebbe essere standard per le macchine di produzione a less che tu non scriva un codice perfetto come me … in movimento); questi errori possono anche essere catturati, dando uno sguardo a qualsiasi intoppo nel codice, usando set_error_handler spiegato in seguito.

Eccezioni gettanti

Le eccezioni sono diverse dagli errori in tre modi principali:

  1. Il codice che li gestisce può essere lontano dal luogo da cui sono stati lanciati. Lo stato variabile dell'origine deve essere passato esplicitamente al constructor Exception, altrimenti si ha solo la traccia dello stack.
  2. Il codice tra l'exception e il catch viene saltato del tutto, mentre dopo un errore si verifica (e non è stato fatale) il codice continua ancora.
  3. Possono essere estesi dalla principale class Exception ; questo ti permette di catturare e gestire eccezioni specifiche, ma lascia che altri si riempiano lo stack fino a quando non vengono catturati da un altro codice. Vedi anche: http://www.php.net/manual/en/language.exceptions.php

Un esempio di lancio di eccezioni viene fornito in seguito.

Gestione degli errori

Catturare e gestire gli errori è piuttosto semplice registrando un gestore di errori, ad esempio:

 function my_error_handler($errno, $errstr, $errfile = 'unknown', $errline = 0, arrays $errcontext = arrays()) { // $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 performsd } set_error_handler('my_error_handler'); 

Per i calci, puoi trasformare tutti gli errori in ErrorException e registrando il seguente gestore degli errori (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"); 

Gestire le eccezioni

Nella maggior parte dei casi, gestisci le eccezioni il più vicino ansible al codice che ha causato la concessione di piani di backup. Ad esempio, si tenta di inserire un record del database e viene generata un'exception del vincolo della chiave primaria; è ansible ripristinare aggiornando il record (progettato come la maggior parte dei database in grado di gestirlo da soli). Alcune eccezioni non possono essere gestite localmente, quindi devi farle cadere a cascata. Esempio:

 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', arrays('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 scivolosa

Quindi cosa succede quando non si rileva un'exception da nessuna parte? Puoi prenderlo anche usando 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'); 

Questo non è incoraggiato a less che tu non abbia modo significativo di gestire l'exception in qualsiasi parte del tuo codice.

Registrazione dell'errore / exception

Ora che stai gestendo l'errore devi registrarlo da qualche parte. Per il mio esempio, utilizzo un progetto che Apache ha portto da Java a PHP, chiamato LOG4PHP . Ce ne sono altri, ma illustra l'importnza di una struttura di logging flessibile.

Usa i seguenti concetti:

  1. Logger : entity framework; con nome che eseguono la logging per conto dell'utente; possono essere specifici di una class nel tuo progetto o condivisi come un logger comune,
  2. Appendici : each richiesta di registro può essere inviata a una o più destinazioni (e-mail, database, file di text) in base a condizioni predefinite (come il livello di registro),
  3. Livelli: i registri sono classificati dai messaggi di debug agli errori fatali.

Utilizzo di base per illustrare diversi livelli di messaggi:

 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'); 

Usando questi concetti è ansible modellare una struttura di logging piuttosto potente; ad esempio, senza modificare il codice precedente, è ansible implementare la seguente configuration:

  1. Raccogli tutti i messaggi di debug in un database per gli sviluppatori; potresti disabilitare questo sul server di produzione,
  2. Raccogli gli avvertimenti in un file giornaliero che potresti submit via email alla fine della giornata,
  3. Avere email immediate inviate su errori fatali.

Definirlo, quindi usarlo 🙂

 define('ERRORLOG_PATH', '/var/tmp/my-errors.log'); error_log($e->getMessage(), 3, ERRORLOG_PATH); 

In alternativa, basta rendere opzionale il terzo parametro di error_log , error_log default sul path desiderato.

Se hai ancora bisogno di un modo personalizzato di gestire i registri (es. Non vuoi usare il trigger_error standard ()), ti consiglio di consultare Zend_Log (http://framework.zend.com/manual/en/zend.log .overview.html) per questi motivi:

  1. questo può essere usato come componente indipendente, ZF non è un framework full-stack. Puoi copiare solo Zend_Loader e Zend_Log namespace, istanziare Zend_Loader e usarlo. Vedi sotto:

     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. Vi sono state offerte molte librerie di logging, ma credo che il team di Zend (fondatori di PHP lang) sappia cosa fanno

  3. Puoi usare qualsiasi scrittore (database, STDOUT – vedi sopra, file, qualunque cosa, puoi personalizzarlo per scrivere il tuo per submit messaggi di log anche a un servizio web)
  4. livelli di log
  5. potrebbe cambiare il formato del registro (ma quello che è out-of-box è fantastico per la mia mente). L'esempio sopra con formattatore standard produrrà qualcosa di simile a questo:

    2012-05-07T23: 57: 23 + 03: 00 INFO (6): messaggio informativo

  6. basta leggere il riferimento, potrebbe essere configurato per catturare gli errori php

Come aggiunta, per la logging degli errori (e di fatto per tutti i log) userei il dispatcher di events, come fa il framework symfony.

Dai un'occhiata a questo componente sf (la sua dipendenza molto leggera, l'integer framework non è richiesto, ci sono forse 3 classi php rilevanti e 2 interfacce)

https://github.com/symfony/EventDispatcher

in questo modo puoi creare il dispatcher da qualche parte nel bootstrap dell'applicazione:

 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 }); 

Quindi puoi generare un evento in qualsiasi posto del tuo codice da qualcosa di simile

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

Ovviamente è ansible suddividere la class di events con i propri events:

 class LogEvent extends GenericEvent { public function __construct($message, $priority = 'INFO') { parent::__construct('application.log', arrays('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')); 

Ciò consentirà anche di creare events personalizzati come ExceptionEvent

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

E gestirli di conseguenza.

vantaggi

  • separate la logica di logging dalla vostra applicazione
  • puoi facilmente aggiungere e rimuovere i logger in runtime
  • puoi facilmente registrare quanti logger vuoi (es. DebugLogger che registra tutto in un file di text, ErrorLogger che registra solo errori in error_log, CriticalLogger che registra solo errori critici nell'ambiente di produzione e li invia via email all'amministratore, ecc.)
  • è ansible utilizzare il dispatcher di events per più cose rispetto alla semplice logging (in effetti per each lavoro per cui è appropriato il model di osservatore)
  • il logger reale diventa nient'altro che "dettagli di implementazione" – è così facile da sostituire che non import where vanno i tuoi log – sarai in grado di sostituire la destinazione del log in qualsiasi momento senza wherer refactoring i nomi dei tuoi methods, o cambiare nulla nel codice.
  • sarà facile implementare una logica di routing log complessa o un formato di log di modifica globale (configurando i logger)
  • tutto diventa ancora più flessibile se si utilizza l'integrazione delle dependencies sia per gli ascoltatori (logger) che per il dispatcher (in classi che notificano l'evento del registro)

Registrazione effettiva

Come già affermato da qualcuno, consiglierei di andare con la libreria pronta all'uso, come menzionato Monolog, Zend_Log o log4php, non c'è probabilmente alcun motivo per codificare queste cose a mano (e l'ultima cosa che vuoi è un errore logger !)

PS: Tratta gli snippet di codice come pseudo-codice, non li ho testati. I dettagli possono essere trovati nei documenti delle biblioteche menzionate.

Se la modalità di gestione degli errori di PHP non è abbastanza flessibile per te (ad esempio a volte vuoi accedere al database, a volte al file, a volte qualsiasi altra cosa), devi usare / creare un framework di logging PHP personalizzato.

Puoi sfogliare la discussione in https://stackoverflow.com/questions/341154/php-logging-framework o semplicemente andare e dare la scelta migliore, KLogger , una prova. Non sono sicuro, tuttavia, se support le destinazioni personalizzate per la logging. Ma per lo less, è una lezione piccola e di facile lettura e dovresti essere in grado di estenderla ulteriormente per le tue esigenze.

Vado con la soluzione di logging di Tom vand der Woerdt, la più semplice e la più efficace per le tue esigenze.

Per quanto riguarda l'altra domanda:

Non è necessario catturare / rilanciare l'exception all'interno della function a less che non ci sia un tipo specifico di exception per cui si ha una soluzione.

Un esempio un po 'semplicistico:

 define('ERRORLOG_PATH', '/var/tmp/my-errors.log'); function do_something($in) { if (is_good($in)) { try { return get_data($in); } catch (NoDataException $e) { // Since it's not too big a deal that nothing // was found, we just return false. return false; } } else { throw new InvalidArguementException('$in is not good'); } } function get_data($data) { if (!is_int($data)) { InvalidArguementException('No'); } $get = //do some getting. if (!$get) { throw new NoDataException('No data was found.'); } else { return $get; } } try { do_something('value'); } catch (Exception $e) { error_log($e->getMessage(), 3, ERRORLOG_PATH); die ('Something went wrong :('); } 

Qui prendi solo NoDataException perché hai qualche altra logica per risolverlo, tutti gli altri errori ricadono sul primo catch e vengono gestiti dal catch superiore perché tutte le eccezioni generate devono a un certo punto della loro gerarchia ereditare da Exception .

Ovviamente se si lancia nuovamente Exception (al di fuori della try {} iniziale try {} o nella parte superiore della catch {} ), lo script verrà chiuso con un errore Eccezione non rilevata e la logging degli errori viene persa.

Se si voleva andare fino in fondo, si potrebbe anche implementare una function di gestione degli errori personalizzata usando set_error_handler() e inserire anche la logging.

Ci sono due sfide da affrontare. Il primo è quello di essere flessibili nel logging su diversi canali. In questo caso dovresti dare un'occhiata ad esempio a Monolog .

La seconda sfida consiste nell'intrecciare il log nella tua applicazione. Imho il caso migliore è no per usare la logging in modo esplicito. Qui per esempio l' orientamento dell'aspetto è utile. Un buon campione è flow3 .

Ma questa è più una visione a volo d'uccello sul problema …

Uso la mia function che mi consente di scrivere più tipi di file di registro impostando o modificando il secondo parametro.

Supero le domande concettuali che mi stai ponendo riguardo a "qual è la strada giusta" per farlo, includendo la function di registro in una libreria di funzioni che considero "native" per i miei progetti di sviluppo. In questo modo posso considerare queste funzioni come parte del php "MY", come date() o time()

In questa versione di base di dlog, gestisco anche gli arrays. mentre inizialmente lo usavo per registrare gli errori, ho finito per usarlo per altri tracciati a breve termine "veloci e sporchi", come la logging delle volte in cui il codice è entrato in una determinata sezione e gli accessi degli utenti, ecc.

 function dlog($message,$type="php-dlog") { if(!is_arrays($message) ) $message=trim($message); error_log(date("m/d/Y h:i:s").":".print_r($message,true)."\n",3, "/data/web/logs/$_SERVER[HTTP_HOST]-$type.log"); } 

La maggior parte dei logger di errore e dei logger di eccezioni sono inutili per la maggior parte delle persone perché non hanno accesso ai file di registro.

Preferisco usare un gestore di errori personalizzato e un gestore di eccezioni personalizzato e avere, durante la produzione, errori di registro direttamente nel database se il sistema è in esecuzione su un database.

Durante lo sviluppo, quando vengono impostati display_errors, non registrano nulla poiché tutti gli errori vengono generati nel browser.

E come nota a margine: non fare in modo che il tuo gestore di errori personalizzato generi eccezioni! È una pessima idea Può causare errori nel gestore buffer e in alcune estensioni. Inoltre alcune funzioni PHP di base come fopen () causano un avviso o un avviso in caso di errore, queste dovrebbero essere gestite di conseguenza e non dovrebbero arrestare l'applicazione con un'exception.

La menzione di avere il gestore degli errori che genera eccezioni nella documentazione di PHP è un bug di note.

Come afferma KNL, che è giusto, ma sfortunatamente non ancora documentato, l'errore di lanciare eccezioni non è raccomandato dagli sviluppatori PHP e qualcuno ha fatto un errore nella documentazione. Può infatti causare bug con molte estensioni quindi non farlo.

Questo è già stato discusso su #PHP su irc.

"Tuttavia, gli errori possono essere semplicemente tradotti in eccezioni con ErrorException." su http://php.net/manual/en/language.exceptions.php verrà rimosso.