3.4 Die Action-Controller 

Alle Action-Controller müssen ein einfaches Interface implementieren, um vom Controller angesprochen zu werden:
interface gpBlogAction
{
public static function registerSlots();
}Listing 3.10 Interface für Aktionen
Wie Sie bereits in Abschnitt 3.3.2, »Initialisierung«, gesehen haben, ruft der Controller die statische Methode registerSlots() für jeden Action-Controller auf, damit dieser seine bereitgestellten Slots registrieren kann. Sie haben ebenfalls in diesem Abschnitt gesehen, dass Action-Controller, abgesehen vom offiziellen PHP-Interface, einer weiteren Konvention unterliegen: Alle Slots, die in der $actionSignals-Sammlung des Controllers registriert werden, müssen genau zwei Parameter erwarten: ein Objekt vom Typ ezcUrl und eine Instanz von ezcUrlConfiguration.
Des Weiteren sollten die Slot-Methoden statisch definiert sein. Ein dynamischer Aufruf wäre zwar auch möglich, ist aber hier nicht vorgesehen und zur Realisierung müssten Klimmzüge vollbracht werden, beispielsweise dass eine Aktion sich selbst innerhalb von registerSlots() instanziiert und die Instanz in einer Art Singleton bereitstellt. Ein Nachteil wäre auch, dass unnötig Objekte erzeugt würden, die mit hoher Wahrscheinlichkeit gar nicht verwendet werden. Bei jedem Request wird im Normalfall nur eine Aktion ausgelöst, im Gegensatz dazu ist es jedoch gut möglich, dass mehrere Dutzend Aktionen registriert sind. Würde jeder dieser Aktionen eine Instanz ihres Action-Controllers erzeugen, führte dies zu einer großen Menge unnötiger Objekte, die mit nur geringer Wahrscheinlichkeit überhaupt benötigt würden. Sollten Sie dennoch eine Instanz der Action-Klasse bei der Behandlung des Slots benötigen, können Sie diese immer noch während der Ausführung des Slots direkt erzeugen. Informationen, die zwischen dem Aufruf von registerSlots() und der Ausführung des eigentlichen Slots gespeichert werden müssen, können über statische Attribute transportiert werden.
3.4.1 Ein einfacher Action-Controller 

Der im Folgenden vorgestellte Action-Controller dient der Anzeige von Einträgen des GP-Blogs. Die einzelnen Slot-Methoden werden, wie Sie es bereits aus vorhergehenden Abschnitten dieses Kapitels wissen, mit Pseudo-Leben gefüllt. Im weiteren Verlauf des Buches werden die Methoden konkret ausgestaltet, sobald die entsprechenden Komponenten besprochen werden. Die Action-Klasse gpBlogActionEntryDisplay ist dafür zuständig, eine Liste der Blog-Einträge anzuzeigen oder einen einzelnen Blog-Eintrag zu präsentieren:
class gpBlogActionEntryDisplay implements gpBlogAction
{
public static function registerSlots()
{
}
public static function showEntry( ezcUrl $url,
ezcUrlConfiguration $config )
{
}
public static function listEntries( ezcUrl $url,
ezcUrlConfiguration $config )
{
}
}Listing 3.11 Signatur der Display-Aktion
Die Registrierung der Slots erfolgt, wie Sie es bereits vom Haupt-Controller (Abschnitt 1.3.2, »Aufbau der Beispielanwendung«) her kennen. Allerdings werden diesmal Slots auf dem $actionSignals Attribut registriert:
public static function registerSlots()
{
gpBlogController::getInstance()->actionSignals->connect(
"show_entry",
array( __CLASS__, "showEntry" )
);
gpBlogController::getInstance()->actionSignals->connect(
"list_entries",
array( __CLASS__, "listEntries" )
);
}Listing 3.12 Signale der Display-Aktion für einen Eintrag registrieren
Sie sehen, dass an dieser Stelle das Singelton-Pattern für den Controller zum Einsatz kommt: Mit Hilfe von gpBlogController::getInstance() wird die einzelne Instanz des Controllers geholt, deren Attribut $actionSignals angesprochen wird. Die Aktion registriert die beiden Slots show_entry und ilist_entries, welche auf die entsprechenden Methoden verweisen. Mit Hilfe der beiden Slot-Namen kann die entsprechende Aktion von nun an über die URL des GP-Blogs angesprochen werden. Die Konstante __CLASS__ enhält immer den Namen der Klasse in der sich die Programmzeile befindet, womit in diesem Beispiel statische Methoden der aktuellen Klasse referenziert werden.
public static function listEntries( ezcUrl $url,
ezcUrlConfiguration $config )
{
gpBlogController::getInstance()->mainSignals->emit(
"display",
"list_entries",
array(
"text" => "Entries would by listed now..."
)
);
}Listing 3.13 Vorläufiger Funktionsrumpf listEntries()
Die listEntries()-Methode sendet das Signal display und übergibt hierbei die anzuzeigenden Einträge. Natürlich noch nicht konkret, da noch keine Möglichkeit zur Verfügung steht, die Einträge auszulesen. Diese wird in Kapitel 5, »Konfiguration«, nachgerüstet. Wie Sie bereits aus Abschnitt 3.3.3, »Signale verarbeiten«, wissen, erwartet der display-Slot neben den anzuzeigenden Daten den Namen eines Templates. Das Template für die Aktion heißt hier ebenfalls list_entries.
| Testen der ersten Aktion |
|
Wenn Sie bereits die erste Stufe der Beispielapplikation zum Testen installiert haben (Abschnitt 1.3.3, »Testen des GP-Blogs«), können Sie die soeben gesehene Aktion auch sofort ausprobieren. Verwenden Sie einfach die URL http://gpblog/list_entries und beobachten Sie die Ausgabe. Achten Sie darauf, die URL, falls nötig, an Ihre Umgebung anzupassen! |
Die Methode zur Verarbeitung des display_entry-Signals ist bereits mit ein wenig mehr Leben gefüllt. Auch wenn noch keine echten Daten bereitgestellt werden können, wird bereits die ID des anzuzeigenden Eintrags aus der URL extrahiert:
public static function showEntry( ezcUrl $url,
ezcUrlConfiguration $config )
{
$config->addOrderedParameter( "id" );
$url->applyConfiguration( $config );
if ( ( $id = $url->getParam( "id" ) ) === null )
{
gpBlogController::getInstance()->mainSignals->emit(
"error",
"No valid entry ID provided. The link you've
been following seems to be broken."
);
return;
}
gpBlogController::getInstance()->mainSignals->emit(
"display",
"schow_entry",
array(
"text" => sprintf(
"Some data from entry %s should be displayed.",
(int) $url->getParam( "id" )
),
)
);
}Listing 3.14 Verarbeitung von URL-Parametern mit Konfiguration
Dem vom Controller übergebenen ezcUrlConfiguration-Objekt wird zunächst ein neuer Parameter hinzugefügt: Die ID des anzuzeigenden Blog-Eintrags. Damit die Instanz von ezcUrl über den neuen Parameter in Kenntnis gesetzt wird, müssen Sie die Konfiguration erneut auf das Objekt anwenden. Anschließend wird überprüft, ob der entsprechende Parameter übergeben wurde. Ist dies nicht der Fall, liefert getParam() einen null-Wert zurück. Ohne ID weiß die Aktion nicht, welcher Eintrag angezeigt werden soll und kann ihre Arbeit nicht fortführen. Deshalb wird in diesem Fall ein error-Signal gesendet und die Methode daraufhin beendet.
Falls eine ID übergeben wurde, sollte der Eintrag mit dieser Nummer aus der Datenbank gelesen werden. Aktuell wird aber lediglich das display-Signal gesendet, mit einem Template namens show_entry und einem Text als Parameter, welcher die ID des Artikels beinhaltet.
| Achtung: ezcUrl schützt nicht |
|
Wie Sie sicher bemerkt haben, wird die aus der URL extrahierte ID vor der Übergabe an die display-Funktion in den Datentyp Integer umgewandelt. Dies ist notwendig, da ezcUrl keinerlei Entwertung der übergebenen Parameter vornimmt. Ein potentieller Angreifer könnte also HTML-Code in die ausgegebene Webseite einschleusen, wenn Sie keine entsprechende Sicherheitsmaßnahme anwenden oder Sie die extrahierten Daten zum Beispiel in einer SQL-Abfrage verwenden. In späteren Kapiteln werden Sie zwei Komponenten kennenlernen, die Sie bei der Absicherung gegen solche Attacken unterstützen: |
|
|
3.4.2 Einträge editieren 

In stage01/, der Beispielanwendung auf Ihrer Buch-CD, ist noch eine weitere Aktions-Klasse implementiert, auf die wir an dieser Stelle kurz eingehen wollen. Die Klasse gpBlogActionEntryEdit beinhaltet vier Aktionen:
- edit_entry
- create_entry
- save_entry
- save_entry_success
Die Aktionen edit_entry und create_entry zeigen jeweils ein Formular an, um einen Eintrag zu bearbeiten beziehungsweise einen neuen Eintrag zu erstellen. Beide Formulare werden dann an die Aktion save_entry übermittelt. Mit Hilfe der Aktion save_entry_success wird dem Benutzer eine Erfolgsmeldung angezeigt, falls die Bearbeitung des gewünschten Eintrags erfolgreich war. Auf die ausführliche Darstellung der Aktionen create_entry, edit_entry und save_entry_success wird an dieser Stelle verzichtet. Sie beinhalten im aktuellen Stadium nichts, was Sie bisher nicht gesehen hätten. Gleiches gilt für die Methode registerSlots() der Aktions-Klasse; auch sie registriert lediglich die benötigten Slots und leitet sie auf entsprechende statische Methoden der Klasse weiter. Sie können sich die Implementierung beider Methoden in stage01/ auf der Buch-CD ansehen. Interessant ist hier aber die Methode save(), welche das Signal save_entry verarbeitet:
public static function save( ezcUrl $url,
ezcUrlConfiguration $config )
{
$config->addOrderedParameter( "id" );
$url->applyConfiguration( $config );
// Eintrag speichern...
$url->setParameter( "action", "save_entry_success" );
$url->setParameter( "id", $id );
gpBlogController::getInstance()->mainSignals->emit(
"redirect",
$url
);
}Listing 3.15 Weiterleitung nach erfolgreicher Verarbeitung
Die save()-Methode registriert zunächst wiederum einen Parameter, um die ID des zu speichernden Eintrags abzufragen. Sollte dieser Parameter nicht existieren, handelt es sich um einen neuen Eintrag. Nach dem erfolgreichen Speichern des Eintrags soll eine Erfolgsmeldung angezeigt werden; tritt hingegen während des Vorgangs ein Fehler auf, wird das entsprechende Fehlersignal gesendet, die Methode beendet und der Code nach dem Kommentar »Eintrag speichern ...« würde nie erreicht. Da die Anzeige der Erfolgsmeldung nicht direkt mit der Speichern-Aktion korreliert, wird im Erfolgsfall eine Weiterleitung auf die Aktion save_entry_success signalisiert, statt wie Sie es bisher kennen, direkt ein display-Signal gesendet. Die Variable $id wird durch die ID des neu erstellten Blog-Eintrags gefüllt, wenn diese Methode später vollständig implementiert wird.
Um das Signal zur Weiterleitung zu erzeugen, benötigen Sie zunächst eine Instanz der Klasse ezcUrl. Nach dem Ausführen der Speichern-Aktion wird das ihr übergebene ezcUrl-Objekt nicht weiter benötigt und daher für den neuen Zweck recycelt. Die beiden benötigten Parameter in der URL wurden bereits zuvor konfiguriert, der Parameter action vom Main-Controller, id kurz vorher. Sie müssen nur noch mit neuen Werten belegt werden, was über die setParameter()-Methode von ezcUrl funktioniert. Anschließend wird das Signal redirect mit dem ezcUrl-Objekt als Parameter gesendet. Sie erinnern sich: Der Controller nimmt nun die Textdarstellung der URL entgegen und sendet damit einen Location-Header an den Browser, womit auf die neue URL weitergeleitet wird.




Ihre Meinung






