Catalyst: Web-Framework für Perl

Seite 5: Aufräumarbeiten

Inhaltsverzeichnis

Eine besondere Rolle spielen die privaten Methoden begin(), auto() und end(). Die spezifischsten begin()- und end()-Varianten sind die jeweils ersten beziehungsweise letzten ausgeführten Aktionen. Konkret hat Foo::Bar::begin() Vorrang vor Foo::begin(), das als unspezifischere Methode komplett ignoriert wird. Alle auto()-Methoden im Controller-Namensraum hingegen führt Catalyst nacheinander (beginnend mit der unspezifischsten) aus. Geben diese Methoden einen wahren Wert zurück, geht die Verarbeitung weiter, sonst ist sofort die ursprüngliche end()-Methode am Zug. Das Bild links veranschaulicht diese Zusammenhänge.

HTTP-Requests durchlaufen in Catalyst eine komplexe Folge von Methodenaufrufen (Abb. 1)

Private index()- und default()-Methoden greifen, wenn sich im Namensraum eines Controllers keine spezialisierte Methode finden lässt. index() hat Vorrang vor default(), kann allerdings keine Argumente entgegennehmen.

Die Beispielanwendung erweitert den standardmäßig vorhandenen Controller lib/iXApp/Controller/Root.pm, anstatt mit script/ixapp_create.pl controller Foo einen neuen anzulegen. Damit entfallen für den Rest dieses Artikels weitere Überlegungen zu Matching-Precedence, Action-Chaining und anderen Feinheiten, mit denen Catalyst das Leben des Programmierers versüßt, Autoren und Neulinge aber in den Wahnsinn treiben kann.

Als Erstes soll die Anwendung alle Tagebucheinträge anzeigen. Dazu benutzt sie die erwähnte index()-Methode, die Abrufe der Document-Root (http://localhost:3000/) auswertet:

sub index : Private {	 my ($self, $c) = @_;  
# Alle DB-Objekte an den View übergeben.
$c->stash->{entries} = [ $c->model->all ];
# Template-Datei für RenderView festlegen.
$c->stash->{template} = 'index';
}
# Kontrolle an den View abgeben
sub end : ActionClass('RenderView') {}

Da das Beispiel nur ein Modell benutzt, ist Journal::Entry in ixapp.yml als Standardmodell festgelegt, das Catalyst bei jedem Aufruf von $c->model() zurückgibt. Alternativ wählte ein Aufruf der Form $c->model('Foo') ein anderes Modell aus.

Der Stash (Lager) $c->stash nimmt Daten auf, die zwischen Aktionen ausgetauscht werden sollen oder die die Anwendung an den View übergibt. Das Beispiel schickt so alle Datenbankobjekte in einem Array und den Namen des anzuzeigenden Templates per Stash an den View.

Hat es die Aktion abgearbeitet, ruft Catalyst die end()-Methode auf. Sie führt die ActionClass „RenderView“ aus, die wiederum die Kontrolle an den View übergibt. Er stellt das Template root/index dar, das die Einträge absteigend sortiert ausgibt. Dazu nutzt es für jeden Eintrag des Tagebuchs das Template item, das jeweils Titel und Text jedes Eintrags liefert:

[% FOREACH entry = entries.reverse %]

[% INCLUDE item entry %]

[% END %]
<p>Eintrag
[[%c.uri_for('edit')%] hinzufügen]
</p>

Auf dem im View als c verfügbaren Kontext-Objekt kann man die Catalyst-Funktion uri_for() aufrufen, die aus dem übergebenen Action-Pfad und beliebig vielen Argumenten eine gültige URI (hier einfach „/edit“) erzeugt. Dies vermeidet fest kodierte URIs und spart Ärger beim URI-Encoding.

Als Nächstes lernt die Applikation das Hinzufügen und Bearbeiten der Tagebucheinträge, was die Aktionen edit und do_edit ( Listing 1) übernehmen.

sub edit : Local {

my ($self, $c, $id) = @_;

# Eintrag anhand der ID finden und übergeben.
$c->stash->{entry} = $c->model->find($id);
# Eintrag zum Editieren/Hinzufügen anzeigen.
$c->stash->{template} = 'edit';
}

Beim Hinzufügen bekommt edit keine ID übergeben, sodass es lediglich das gleichnamige Template anzeigt. Beim Bearbeiten hingegen reicht es das anhand der ID gefundene Datenbankobjekt an den View weiter.