Skip to content

Instantly share code, notes, and snippets.

@xrstf
Created August 25, 2012 02:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xrstf/3459300 to your computer and use it in GitHub Desktop.
Save xrstf/3459300 to your computer and use it in GitHub Desktop.
Sally 0.7 Controller-Erweiterung

Problem

Konkret ist der Content-Controller vom Sally-Backend problematisch. Er verlässt sich u.a. darauf, dass der nette Sally-Dispatcher seine Exceptions fängt. Das führt allerdings auch dazu, dass anstatt der "Inhalt"-Überschrift die "Unterwartete Exception"-Meldung auftaucht. Was nicht wirklich stimmt, da einige der Exceptions bewusst vom Controller geworfen werden (also nicht unerwartet sind).

Gleichzeitig taucht in vielen Controllern immer wieder das Muster auf, dass eine allgemeine init()-Methode angelegt wird, die von jeder Action als erstes aufgerufen wird. Teils ist die Methode so komplex, dass sie a) nicht mehrmals aufgerufen werden darf und b) die Ausführung der eigentlichen Action stoppen kann.

Vorschlag

Beide Probleme können sowohl vom Core als auch von Controller-Autoren sehr leicht gelöst werden, wenn wir den Dispatcher ein wenig erweitern. Ich schlage vor, ein neues Interface sly_Controller_Generic einzuführen, das in etwa so gestaltet ist:

interface sly_Controller_Generic {
    public function genericAction($action);
}

Der Dispatcher würde dieses Interface im Pseudo-Code wie folgt auswerten:

function dispatch($controller, $action) {
   if ($controller implements sly_Controller_Generic) {
      return $controller->genericAction($action);
   }

   $method = strtolower($action).'Action';
   return $controller->$method();
}

Die genericAction() steht für Controller, die nicht das neue Interface implementieren, weiterhin zur Verfügung. Für alle anderen werden außer genericAction() eh keine Action-Namen benötigt. Hier tritt also kein Konflikt auf.

Die generische Action kann als beliebig komplexer Wrapper dienen.

function genericAction($action) {
   // stuff, der normalerweise in der init() lieg
   sly_Core::getLayout()->pageHeader('Foo');

   // error handling
   try {
      $method = strtolower($action).'Action';
      return $controller->$method();
   }
   catch (Exception $e) {
      // Auf Wunsch kann hier noch zwischen einer Controller-spezifischen
      // Exception wie "objekt nicht gefunden" oder einer System-Exception
      // wie "Datenbank tot" unterschieden werden.

      if ($e instanceof Controller_Specific_Exception) {
         print sly_Helper_Message::warn($e->getMessage());
      }
      else {
         throw $e;
      }
   }
}

Das wäre eine kleine Änderung am Core, die das Schreiben von Controllern echt erleichtern kann. Gleichzeitig halsen wir uns damit keine komplexen Workflow-Methoden (lifecycle Callbacks) auf.

Nebenbei ermöglicht diese Erweiterung gänzlich generische Controller :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment