Frontend-Controller

SallyCMS erlaubt es, Controller nicht nur im Backend (über AddOns), sondern auch im Frontend zu verwenden. Im Standard-Umfang von Sally sind zwei Controller bereits enthalten: Der Artikel-Controller rendert Artikel (und ist der Standard-Controller) und der Asset-Controller steuert den Asset-Cache.

Frontend-Controller müssen dem Namensschema sly_Controller_Frontend_Xxx folgen und über eine Route ansprechbar gemacht werden. Die Implementierungen können überall liegen, wo sie vom Autoloader gefunden werden können (also sowohl in AddOns als auch in develop/lib).

Warnung

Es kann immer nur ein Controller gleichzeitig ausgeführt werden. Daher gibt es in Frontend-Controllern keinen Artikelkontext (da kein Artikel gesucht wurde). Ein Aufruf von sly_Core::getCurrentArticle() gibt daher null zurück. Ebenso gibt es keine aktuelle Sprache.

Beide Angaben können vom Controller natürlich jederzeit gesetzt werden. So könnte die Sprache auf die voreingestellte Sprache oder der aktuelle Artikel auf den Seiten-Startartikel gesetzt werden.

Beispiel-Controller

Wir entwickeln im Folgenden einen Controller, der einfach nur das Wort hallo ausgibt. Dazu legen wir einen sly_Controller_Frontend_Hello an und legen ihn in develop/lib/sly/Controller/Frontend/Hello.php ab.

<?php

/**
 * Unser Hello-Controller
 *
 * Controller müssen mindestens das Interface sly_Controller_Interface implementieren.
 * In 99% der Fälle wird man sich aber eher von sly_Controller_Frontend_Base
 * ableiten. Dort wird bereits das view-Verzeichnis auf develop/views festgelegt
 * und der Zugriff für alle Besucher erlaubt.
 */
class sly_Controller_Frontend_Hello extends sly_Controller_Frontend_Base {
	/**
	 * Die Standard-Action
	 *
	 * Wenn keine Action in der URL gefunden wurde, wird diese Action verwendet.
	 *
	 * Actions sollten immer *entweder* ihre Ausgabe direkt printen *oder* ein
	 * sly_Response-Objekt zurückgeben (sehr empfohlen). Das Response-Objekt
	 * erlaubt es, Header zu sammeln und ggf. von Listenern auf SLY_SEND_RESPONSE
	 * noch einmal verarbeiten zu lassen.
	 */
	public function indexAction() {
		$response = new sly_Response('hallo');
		$response->setContentType('text/plain', 'UTF-8');

		return $response;
	}

	/**
	 * Eine weitere Action
	 *
	 * Diese Action nutzt einen Parameter aus der Route (Teil des virtuellen
	 * Request Filename, nicht aus dem Query-String), um jemanden persönlich
	 * zu begrüßen.
	 */
	public function greetAction() {
		// aktuelle App (Frontend-App)
		$app = sly_Core::getCurrentApp();

		// die Frontend-App (und nur sie!) gibt den Router preis
		$router = $app->getRouter();

		// die getroffene Route hat weitere Daten, auf die wir via ->get()
		// zugreifen können.
		$name = $router->get('name');

		// as usual
		$response = new sly_Response('hallo '.$name.'!');
		$response->setContentType('text/plain', 'UTF-8');

		return $response;
	}
}

Routing

Der Router (sly_Router_Base) versucht, anhand von URL-Mustern die angefragte URL aufzulösen und dabei den Controller (und ggf. weitere Parameter) zu ermitteln.

Im Normalfall gibt es in Sally keine vordefinierten Routen. Die Frontend-App erlaubt es allerdings, im SLY_FRONTEND_ROUTER-Event eigene Routen zu definieren. Dies nutzen wir nun dazu, unseren Hello-Controller ansprechbar zu machen.

Bemerkung

Das Hinzufügen der Routen kann überall passieren, wo auf dieses Event gelauscht werden kann. Aus Komfortgründen liegt der Code in diesem Beispiel direkt in der Controller-Klasse. Überlicherweise sollten die Routen allerdings nicht im Controller definiert werden!

<?php


class sly_Controller_Frontend_Hello extends sly_Controller_Frontend_Base {
	// ...

	/**
	 * Callback für SLY_FRONTEND_ROUTER
	 *
	 * Fügt dem übergebenen Router die Routen für diesen Controller hinzu.
	 *
	 * @param  array $params    Eventparameter
	 * @return sly_Router_Base  der übergebene Router
	 */
	public static function addRoutes(array $params) {
		$router = $params['subject']; // sly_Router_Base

		// Die Reihenfolge der Routen ist von Relevanz! Die erste treffende Route
		// zählt, alle weiteren werden nicht ausgewertet.

		// Jede Route besteht aus zwei Teilen: Das URL-Muster und die zusätzlichen
		// Parameter. Das Muster ist ein regulärer Ausdruck, der zusätzlich
		// Platzhalter der Form ':placeholder' erlaubt. Diese Platzhalter matchen
		// auf [a-z_][a-z0-9-_]* und erlauben es, direkt auf die gematchen Werte
		// zuzugreifen.

		// Route zur greet Action
		// ':name' steht später ebenso wie 'controller' über ->get() zur Verfügung.
		// 'controller' gibt den Namen des Controllers an, der den Request handeln
		// soll. 'action' gibt den Namen der Action an (ohne das 'Action'-Suffix).
		// Beide Werte müssen vorhanden sein, wobei es OK ist, wenn sie in dem
		// URL-Muster als Platzhalter auftauchen. Treffer im Muster haben Vorrang
		// vor den zusätzlich gegebenen Werten (diese fungieren also als Default-
		// Werte).

		$router->addRoute('/hello/:name', array(
			'controller' => 'hello',
			'action'     => 'greet'
		));

		// Route zum allgemeinen Controller

		$router->addRoute('/hello', array(
			'controller' => 'hello'
			// keine 'action', also wird 'index' angenommen
		));

		// und den Router an den nächsten Listener weitergeben
		return $router;
	}
}

Event-Konfiguration

Die addRoutes()-Methode muss nun nur noch beim Feuern des Events ausgeführt werden. Dazu registrieren wir über eine beliebige Konfigurationsdatei in develop/config einen Listener:

LISTENERS:
   SLY_FRONTEND_ROUTER: ['sly_Controller_Frontend_Hello::addRoutes']

Bemerkung

Sollte man in einem Addon mehrere Frontend-Controller erstellt haben, dann sollten die verschiedenen Controller wie folgt dargestellt werden

LISTENERS:
   SLY_FRONTEND_ROUTER: ['sly_Controller_Frontend_Hello::addRoutes','sly_Controller_Frontend_Goodbye::addRoutes']

Ergebnis

Wenn alles funktioniert hat, kann man nun im Browser die URL example.com/hello oder example.com/hello/tom aufrufen.

Inhalt

Vorheriges Thema

Frontend-Listeners

Nächstes Thema

Ein Projekt mit Mercurial entwickeln

Diese Seite