Zend Framework – Errorhandling in Modul auslagern

Bei größeren Projekten kommt man evtl. auf die Idee das Errorhandling der Webapplikation in ein eigenes Modul auszulagern. Mit Hilfe des Zend Frameworks sind dazu drei Schritte notwendig:

  • Error-Modul anlegen
  • Error-Plugin zum Setzen des Standard-Error-Moduls
  • application.ini und Bootstrap.php der Anwendung konfigurieren


Beginnen wir mit dem Error-Modul. Im Ordner modules legen wir ein neues Modul Error an (vgl. Tutorial 1 Punkt 4). Das Modul benötigt zunächst einen IndexController:

class Error_IndexController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $errors = $this->_getParam('error_handler');
        if (!$errors || !$errors instanceof ArrayObject) {
            $this->view->message = 'You have reached the error page';
            return;
        }
        //Fehlermeldung abhängig vom Typ in das Messageobjekt schreiben
        switch ($errors->type) {
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER:
            case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION:
                // 404 error -- controller or action not found
                $this->getResponse()->setHttpResponseCode(404);
                $priority = Zend_Log::NOTICE;
                $this->view->message = 'Page not found';
                break;
            default:
                // application error
                $this->getResponse()->setHttpResponseCode(500);
                $priority = Zend_Log::CRIT;
                $this->view->message = 'Application error';
                break;
        }

        // Log exception, if logger available
        if ($log = $this->getLog()) {
            $log->log($this->view->message, $priority, $errors->exception);
            $log->log('Request Parameters', $priority, $errors->request->getParams());
        }

        // conditionally display exceptions
        if ($this->getInvokeArg('displayExceptions') == true) {
            $this->view->exception = $errors->exception;
        }

        $this->view->request   = $errors->request;
    }

    /**
     * 
     * Erzeugt ein Logging-Element
     * @return $log
     */
    public function getLog()
    {
        $bootstrap = $this->getInvokeArg('bootstrap');
        if (!$bootstrap->hasResource('Log')) {
            return false;
        }
        $log = $bootstrap->getResource('Log');
        return $log;
    }
}

Passend dazu benötigen wir eine index.phtml im View-Scripts Ordner:

<h1>An error occurred</h1>
  <h2><?php echo $this->message ?></h2>

  <?php if (isset($this->exception)): ?>
  
  <h3>Exception information:</h3>
  <p>
      <b>Message:</b> <?php echo $this->exception->getMessage() ?>
  </p>

  <h3>Stack trace:</h3>
  <pre><?php echo $this->exception->getTraceAsString() ?>
  </pre>

  <h3>Request Parameters:</h3>
  <pre><?php echo $this->escape(var_export($this->request->getParams(), true)) ?>
  </pre>

  <?php endif ?>

Für das Errormodul benötigen wir nun lediglich noch die Bootstrap-Datei, damit das Modul einwandfrei funktionieren kann:

class Error_Bootstrap extends Zend_Application_Module_Bootstrap
{
}

Damit das Error-Handling auch korrekt an das Modul weitergeleitet wird, ist ein Plugin notwendig. Wir erzeugen im Plugin-Ordner einen Ordner Controller. In diesen Ordner legen wir unsere Plugin-Datei ErrorControllerSelector.php ab:

class Plugin_Controller_ErrorControllerSelector extends Zend_Controller_Plugin_Abstract
{
    public function routeShutdown(Zend_Controller_Request_Abstract $request)
    {
        $front = Zend_Controller_Front::getInstance();
        $error = $front->getPlugin('Zend_Controller_Plugin_ErrorHandler');
        $error->setErrorHandlerModule("Error");
        $error->setErrorHandlerController("index");
        $error->setErrorHandlerAction("index");
    }
}

Im Schritt 3 passen wir jetzt unseren Applikationskontext an. Fügt eurer application.ini folgende Zeilen hinzu:

autoloaderNamespaces[] = "Error_"
autoloaderNamespaces[] = "Plugin_"

Die Bootstrap.php der Anwendung wird um die Methode _initPlugins() erweitert und lädt uns das eben angelegte Plugin:

protected function _initPlugins()
{
    $this->bootstrap('frontController');
    $this->getResource('frontController')
           ->registerPlugin(new Plugin_Controller_ErrorControllerSelector());
}

Damit habt ihr das Error-Handling eurer Webapplikation in ein extra Modul ausgelagert.

Kommentar verfassen