• Willkommen im Zend Framework Forum

    ZF1 Zend Framework 1 + ZF2 Zend Framework 2

    Das Zend Framework Forum ist seit 2006 die erste Anlaufstelle für Zend Framework Entwickler in Deutschland. Mit über 70.000 Beiträgen und einer steigenden Nutzerzahl bietet das Forum hilfreiche Themen und ZF-Tutorials für professionelle Entwickler, fortgeschrittene Programmierer sowie Zend Framework Einsteiger.
    Wenn dies Dein erster Besuch in der Zend Framework Community ist, lies bitte zuerst die Hilfe - FAQ durch. Du musst Dich registrieren, bevor Du Beiträge verfassen kannst. Klicke oben auf 'Registrieren', um die Registrierung zu starten. Du kannst auch jetzt schon Beiträge lesen. Hier im Forum findest Du die Zend Framework Hilfe, die Du suchst!

    Grüße an alle Zend Framework Entwickler. Das Team vom Zend Framework Forum!

    Drupal Agentur

Error- und Exception- Handling

SirThxAlot

New member
Hallo zusammen,

Wie wird ein komplettes error und exception handling mithilfe des Zend Frameworks 2 und PHP gelöst?

Ich habe nun verschiedene Forumen nach einer Lösung durchsucht, um Errors und Exceptions zu behandlen mithilfe eines Error Handlers.
Dabei bin ich leider nur auf Bruchteile gestossen, welche ich mir zusammengebastelt habe. Nun interessiert mich wie man das Problem einheitlich
löst, wie geht Ihr vor?

Aufgabenstellung:

  • Es dürfen keine Fehler direkt am Bildschirm ausgegeben werden:
    Keine Anzeige von trigger_error(E_ALL) oder throw new Exception().
  • Der Administrator soll im Fehlerfall detailiert informiert werden.
  • 404 (file not found) auf eigene Seite verweisen.
  • 404 informieren falls intern verursacht.
  • 500 auf eigene Seite veweisen.
  • Loggen von errors und exceptions egal welcher Art.
  • Log inkl. stack trace in Datenbank oder Logfile
Ich danke schonmal im voraus für Eure vorschläge und möchte nachfolgend das Aufführen, was ich mir bisher zusammengebastelt habe.
Würde mich über Feedback zu meiner Lösung ebenfalls freuen.

Wenn Ihr mögt meine Lösung bisher:

Komponenten:
  • ini_set(...) in /public/index.php [front controller]
  • Zend\Stdlib\ErrorHandler, übernimmt das Error Handling
  • Zend\Mvc\Application, übernimmt Exception Handling (glaube ich zumindest?)
  • MyApp\Error\Listener (EVENT_DISPATCH_ERROR & EVENT_RENDER_ERROR)
  • Zend\Log\Logger übernimmt logging
Schritt 1 (/public/index.php) [Front Controller]
Ich beginne damit die PHP.ini Konfigurationen mithilfe der Funktion ini_set(),
betreffend des error handlings zu setzen:
PHP:
<?php
ini_set('error_reporting', E_ALL);
ini_set('display_errors', false);
ini_set('log_errors', true);
ini_set('error_log', "/data/log/php-errors.log");
Danach binde ich die Datei 'init_errorhandler.php' ein:
PHP:
use Zend\Log\Logger;
use Zend\Log\Writer\Stream;
use Zend\Log\Formatter\Simple;
use Zend\Stdlib\ErrorHandler;

ErrorHandler::clean();
ErrorHandler::start(E_ALL);

$log_error = function($stream = null, $dateFormat = 'Y-m-d H:i:s')
{    
    $logger = new Logger();
    $formatter = new Simple(
        '%timestamp% - %priorityName% (%priority%)'."\n".'%message% %extra%'.
        "\n".str_repeat('-', 80),
        $dateFormat
    );
    $writer = new Stream($stream);
    $writer->setFormatter($formatter);
    $logger->addWriter($writer);
    Logger::registerErrorHandler($logger);
};

$log_error('data/log/app-errors.log');
Schritt 2 (.../listener/ErrorListener.php)
Dieser Listener wartet auf die beiden Fehler Events: EVENT_DISPATCH_ERROR & EVENT_RENDER_ERROR.
Dabei wird der Listener in der onBootstrap(EventInterface $e)-Methode an den Event-Manager attached:

- .../Module.php -
PHP:
// EventInterface $e
$eventManager   = $e->getApplication()->getEventManager();
$eventManager->attachAggregate(new ErrorListener());
- .../listener/ErrorListener.php -
PHP:
namespace MyApp\Listener;

use Zend\Log\Formatter\Simple;
use Zend\Log\Logger;
use Zend\Log\Writer\Stream;
use Zend\EventManager\EventManagerInterface;
use Zend\EventManager\ListenerAggregateInterface;
use Zend\Mvc\MvcEvent;

class ErrorListener implements ListenerAggregateInterface
{
    protected $listeners = array();
    protected $error_log = 'data/log/app-exceptions.log';

    public function attach(EventManagerInterface $events)
    {
        $this->listeners[] = $events->attach(
            MvcEvent::EVENT_DISPATCH_ERROR, array($this, 'logErrorToFile'),
            -1000
        );
        
        $this->listeners[] = $events->attach(
            MvcEvent::EVENT_RENDER_ERROR, array($this, 'logErrorToFile'),
            -1000
        );
    }
    
    public function detach(EventManagerInterface $events)
    {
        foreach ($this->listeners as $index => $listener) {
            if ($events->detach($listener)) {
                unset($this->listeners[$index]);
            }
        }
    }
    
    public function logErrorToFile(MvcEvent $e)
    {
        $exception = $e->getParam('exception');
        
        if ($exception != null) {
            $formatter = new Simple(
                '%timestamp% - %priorityName% (%priority%)'."\n".'%message% %extra%'.
                "\n".str_repeat('-', 80),
                'Y-m-d H:i:s'
            );
        
            $writer = new Stream($this->error_log);
            $writer->setFormatter($formatter);

            $logger = new Logger();
            $logger->addWriter($writer);
        
            $logger->log(Logger::ERR, $exception);
        }
    }
}
Probleme mit dieser Lösung:
  • Ich konnte bisher kein ErrorDocument 500 definieren das funkionierte - einfach leer, wenn Applikation noch nicht gestartet?
    Dies ist zwar mehr ein PHP Problem aber ich denke es hängt mit dem ZF2 zusammen.
  • Die Logging funktion gefällt mir nicht ich möchte ein Logging zentral definieren und beide Klassen
    darauf zugreifen lassen, hier ist zu beachaten das 'init_errorhandler.php' vor der Mvc-Applikation
    integriert wird. - Klasse und Autoloading oder wie? - möchte Zend verwenden und zentral registrieren.
  • Ausserdem ist das tausendfache aufrufen eines Fehlers eine Belastung für den Server, wahrsch. ist
    Datenbank besser - Idee?
 
Zuletzt bearbeitet:

Kaiuwe

Super-Moderator
Willkommen im Forum! :)
Wie wird ein komplettes error und exception handling mithilfe des Zend Frameworks 2 und PHP gelöst?
Ich weiß nicht wie es den anderen Lesern hier geht, aber ich bin zumindest nicht blind. ;)

Schritt 1 (/public/index.php) [Front Controller]
Ob dies überhaupt ein Teil der Anwendungskonfiguration ist und nicht zum Bereich Server gehört, darüber kann mal nachdenken.
Zählt man es selbst zur Anwendungskonfiguration oder man hat keine Wahl – soll passieren –, dann würde ich es in den Ordner „config“ der Anwendung verbannen.

Danach binde ich die Datei 'init_errorhandler.php' ein:
Es reicht auch später, denn wenn schon die Anwendung selbst nicht startet, dann wird wohl grundlegend etwas falsch sein.

Schritt 2 (.../listener/ErrorListener.php)
Gute Idee. Daher hier nur ein Link: Simple logging of ZF2 exceptions | Rob Allen

Ich konnte bisher kein ErrorDocument 500 definieren das funkionierte - einfach leer, wenn Applikation noch nicht gestartet?
Dies ist zwar mehr ein PHP Problem aber ich denke es hängt mit dem ZF2 zusammen.
Hier kann ich dir leider nicht folgen, denn was heißt „einfach leer, wenn Applikation noch nicht gestartet“?

Die Logging funktion gefällt mir nicht ich möchte ein Logging zentral definieren und beide Klassen
darauf zugreifen lassen, hier ist zu beachaten das 'init_errorhandler.php' vor der Mvc-Applikation
integriert wird. - Klasse und Autoloading oder wie? - möchte Zend verwenden und zentral registrieren.
Siehe Beispiel unter dem Link von mir.

Ausserdem ist das tausendfache aufrufen eines Fehlers eine Belastung für den Server, wahrsch. ist
Datenbank besser - Idee?
Hier bin ich verwirrt! Wieso möchtest du einen Fehler „tausendfach“ aufrufen? Und was soll die Datenbank bei dieser Thematik? :confused:
 

SirThxAlot

New member
Hallo Kaiuwe

danke für deine Meinung und Begrüssung wollte mich auch schon vorstellen, weiss nur noch nicht wo ich das machen soll?
Soviel schonmal zu mir, blind bin ich auch nicht, eigentlich ist das meine Frage, wie ich das bisher löse ist mehr Beigemüse,
welches aufzeigen soll was ich eigentlich vorhabe. - ;)

Da ich neu bin versuche ich mal meine erste Aufgabe zu bewältigen und zwar das erstellen einer kleinen Skeleton Application,
nicht verwechseln mit ZF Skeleton App, ich möchte Sie komplett selbst schreiben. So nun nimmt mich mal Grundsätzlich wunder
wie ich ZF2 mit PHP zusammen spielen lassen kann betreffend EH und Exception. - Hierzu noch ein Hinweis ich bin ein Anfänger,
aber so wie ich das verstehe sind exceptions und errors 2-Paar Schuhe? Und ich hab das Gefühl ich bekomme nur zum Thema Exception antworten?

Daher muss man das Thema als Zwitter (PHP und ZF) betrachten ich möchte herausfinden wie ich meine Konfigurationen und "Services" zentral lagern kann so dass diese möglichst
bei allen Fehlern eingreiffen können, d.h auch bevor das Zend Framework registriert wird.

Ausserdem verstehe ich den Zend Error Handler noch nicht, wenn ich einen E_USER_ERROR auslöse (trigger), dann schluckt das Ding den einfach weg, loggt den Fehler und geht zur normalen Seite.
Nicht dass ich das nicht Toll finde, aber ich verstehe nicht ganz was da passiert - eigentlich sollte doch Script abgebrochen werden?

Also Grundsätzlich:
- Was muss beim Error und Exception Handling gemacht werden? (Wenn ich den Ablauf kenne kann ich auch besser suchen wie ich das mache!)
- Welche Komponenten stellt das Zend Framework 2 zur Verfügung?
- Wie löse ich das sauber und zentral, so dass der Client im besten Fall nie einen Fehler mitkriegt,
sollte jedoch das System soweit gestört sein das es infunktionell wird soll Error Page erscheinen.
- Was ist zu beachten.

Gruss
SirThxAlot
 
Zuletzt bearbeitet:

SirThxAlot

New member
Hier kann ich dir leider nicht folgen, denn was heißt „einfach leer, wenn Applikation noch nicht gestartet“?
1) einfach leer:
Bedeutet es kommt die Browser Fehlerseite (Get 500 Internal ... 0B).
Das die MVC-Application Error View nicht angezeigt wird ist mir absoult klar,
nur nicht warum ein definiertes ErrorDocument 500 /... (.htaccess) genommen wird.
Mein Gefühlt leitet mich immer wieder zu diesem Thema: http://stackoverflow.com/questions/5765319/apaches-errordocument-directive-does-not-redirect/5839076#5839076 - CGI?

2) Applikation nicht gestartet:
Hier mal ein paar Szenarien innerhalb des Front Controllers (/public/index.php), stell Euch vor was passiert wenn der trigger_error('pre_app.. ausgelöst wird.
PHP:
@define('PROJECT_ROOT', dirname(__DIR__));

ini_set('error_reporting', E_ALL);
ini_set('display_errors', false);
ini_set('log_errors', true);
ini_set('error_log', PROJECT_ROOT."/data/log/php-errors.log");

//ERROR->
trigger_error('pre_app', E_USER_ERROR);
//<-ERROR

chdir(PROJECT_ROOT);

require_once ('init_autoloader.php');

//ERROR->
#trigger_error('autoregistred zend', E_USER_ERROR);
//<-ERROR

require_once ('init_errorhandler.php');

//ERROR->
#trigger_error('error handler exists', E_USER_ERROR);
//<-ERROR

$config = require_once ('/config/application.config.php');
Zend\Mvc\Application::init($config)->run();
 
Zuletzt bearbeitet:

SirThxAlot

New member
Hier bin ich verwirrt! Wieso möchtest du einen Fehler „tausendfach“ aufrufen? Und was soll die Datenbank bei dieser Thematik?
:D Ich möchte nicht tausend Fehler aufrufen.
Damit meine ich mehr ein PHP spezifisches Thema (aber vielleicht kennt Zend einen Trick).
Das Logging in eine Datei finde ich eigentlich eine Feine Sache, gerade in der Entwicklung ist es einfach und wenn es gut formatiert wurde, findet man
auch seinen Fehler (zumindest immer den vorletzten ;) ).
Ich könnte mir durchaus vorstellen nur die Logging Dateien zu verwenden um mich auf Fehler aufmerksamm zu machen, wenn da nicht ein Problem wäre.
So wie ich das Logging erstelle wird bei jedem Fehleraufruf der Fehler registriert (Tausend Besucher, Tausend Zeilen Code).

Einfacher wäre es doch Fehler anhand von Zeilenummer und Datei zu identifizieren und einmalig zu loggen, hat da jemand eine Idee dazu?


Zum Thema Datenbank, ich höre oft das man Fehler in Datenbanken loggen soll, da man ja den Fehler so einmalig speichern kann.
Persönlich finde ich es von drei Optionen (Mail, Logfile, Log DB) die schlechteste. Da ja wahrscheinlich ein Fehler aufgetreten ist,
gehe ich persönlich davon aus, dass etwas auch mit der Datenbank Verbindung nicht stimmt. Somit frage ich mich hat Zend EH eine
Möglichkeit Prioritäten von Fehlern zu erkennen und kann es den Prioritäten verschiedene Fehlerbehandlungen zuweisen? Bsp.:
Versuche zuerst in Datenbank zu loggen wenn nicht möglich versuche Logfile zu schreiben und wenn alles ned klappt mail().
 
Zuletzt bearbeitet:

SirThxAlot

New member
Es reicht auch später, denn wenn schon die Anwendung selbst nicht startet, dann wird wohl grundlegend etwas falsch sein.
Ja schon aber ist nicht je früher desto besser?
Oder hat das ausführen der MVC-Applikationen und dann das integrieren des ErrorHandlers Vorteile?
 

Kaiuwe

Super-Moderator
Mach mal langsam. Gleich drei Beiträge hintereinander, wo soll da jemand antworten? ;)

SirThxAlot schrieb:
Ja schon aber ist nicht je früher desto besser?
Wie ich bereits geschrieben habe:
Kaiuwe schrieb:
…wenn schon die Anwendung selbst nicht startet, dann wird wohl grundlegend etwas falsch sein.
Ein Problem wird also nicht in der „index.php“ zu suchen sein.
Sollte doch ein Fehler enthalten sein, dann nur ein Syntaxfehler oder ähnliches, was aber schon deine Entwicklungsumgebung meldet oder auch in den Log-Dateien vom Server steht.

SirThxAlot schrieb:
Oder hat das ausführen der MVC-Applikationen und dann das integrieren des ErrorHandlers Vorteile?
Ja, denn so kannst du die Fehlererfassung/das Fehlerauffangen an einer Stelle bündeln. In deinem Ausgangsbeitrag hast du noch zwei Stellen: „init_errorhandler.php“ und „ErrorListener.php“.
 
Oben