Widgets mit dem Zend Framework

Der letzte Artikel ist ja schon etwas länger her und deshalb gibt es als Ausgleich mal wieder einen längeren Artikel.
Es geht darum, wie man sinnvoll ein Widget-Aufbau für das Zend Framework umsetzen kann. Mein Ansatz ist sicherlich nicht
perfekt, aber ein guter Anfang.

Vorausgesetzt wird auch dieses mal wieder eine lauffähige ZF-Anwendung mit Bootstrap-Klasse.

Fangen wir am besten erst einmal damit an, ein Layout zu bauen, in dem verschiedene Spalten (Inhaltsbereiche) zur Verfügung stehen.

	[...]
	<body>
		<div id="container">
			<div id="left">
				<?php echo $this->layout()->left ?>
			</div>
			<div id="content">
				<?php echo $this->layout()->content ?>
			</div>
			<div id="right">
				<?php echo $this->layout()->right ?>
			</div>
		</div>
	</body>
	[...]

Im Content wird ganz normal wie sonst auch der Haupt-Inhalt der Seite angezeigt. Die beiden anderen Spalten werden dann für die
Widgets verwendet.

Als nächstes brauchen wir eine Funktion, die unsere linke und rechte Spalte befüllt. Dazu schreiben wir uns einen abstrakten
Controller, der von allen Controllern erweitert wird.

abstract class Controller_Abstract extends Zend_Controller_Action
{
	// Hier kommt bald unsere Widget-Logik rein
}

Jetzt müssen wir müssen wir uns darüber Gedanken machen, wie die Widgets später aufgerufen werden. Ich habe das so gemacht,
dass man im Controller die Widgets hinzufügt.

class IndexController extends Controller_Abstract
{
	public function init()
	{
		// Navigation links hinzufügen
		$this->addWidget('left', 'navigation');
	}
 
	public function indexAction()
	{
		// Widget xyz rechts hinzufügen
		$this->addWidget('right', 'widgetxyz');
	}
}

Mit der addWidget()-Funktion wird das Widget der Seite hinzugefügt. Wird die Methode in der init() aufgerufen, gilt das Widget
global für den ganzen Controller, andernfalls nur für die angegebene Action.

Der nächste Schritt geht es um die Logik zum Hinzufügen der Widgets. Wir schreiben uns dazu die addWidget()-Funktion in unseren abstrakten
Controller:

	protected $_widgets = array();
 
	public function addWidget($container = 'left', $action)
	{
		$controller = $this->_getParam('controller');
		if(is_array($action))
		{
			$controller = $action[0];
			$action = $action[1];
		}
		$this->_widgets[$container][] = array(
			'action' => $action,
			'controller' => $controller,
			'module' => $this->_getParam('module')
		);
		return $this;
	}

Wir legen zunächst eine Member-Variable $_widets an, in der alle Widgets zwischengespeichert werden. Das Rendern der Widgets kommt
erst später.
Jetzt stellt sich natürlich die Frage, wieso in der addWidget()-Methode so viel Variablen mit dem Namen $controller und $action
auftauchen. Das liegt daran, dass wir die einzelnen Widgets jeweils in eine eigene Action auslagern. So bleiben die Widgets
schön von einander getrennt, man muss aber nicht immer eine eigene Klasse für jedes Widgets anlegen (obwohl es möglich wäre).
Außerdem können die Widgets weiterhin mit den bekannten Funktionen der Zend_View und allen View-Helpern arbeiten.

Hier mal ein Beispiel für o.g. Widgets „widgetxyz“ und „navigation“.

class IndexController extends Controller_Abstract
{
	// init() und indexAction()...
 
	public function navigationAction()
	{
		$this->view->zuweisung = $xyz;
		// Widget-Code
	}
 
	public function widgetxyzAction()
	{
		// Widget-Code
	}
}

Jedes Widget befindet sich also in einer eigenen Action und hat jeweils auch ein eigenes Template, wie normale Actions auch.
Wenn das Widget über addWidget(‚left‘, array(‚controllerxyz‘, ‚widgetxyz‘)) angelegt wurde, könnte man es auch in einen
gesonderten Controller ablegen.

Aber wie wird das Widget jetzt ausgegeben? Dieser letzte Schritt ist wohl der Wichtigste, aber zum Glück nicht so kompliziert,
wie man sich vielleicht denkt. Zur Ausgabe der Widgets verwenden wir nämlich einen ganz normalen View-Helper, der vor dem finalen
Rendering aufgerufen wird. Wir schreiben dazu einfach eine Methode postDispatch() in unseren abstrakten Controller:

abstract class Controller_Abstract extends Zend_Controller_Action
{
	// Übrige Logik
 
	public function postDispatch()
	{
		foreach($this->_widgets as $container => $widgets)
		{
			$html = '';
			foreach($widgets as $widget)
			{
				$html .= $this->view->action($widget['action'], $widget['controller'], $widget['module']);
			}
			$this->getResponse()
				->append($container, $html);
		}
	}
}

Es werden alle Widgets durchlaufen und die jeweilige Action für das Widget aufgerufen. Das gerenderte Ergebnis übergeben wir
dann einfach an das Response-Objekt, das dann die Widget-Ausgabe in der zugewiesenen Spalte ausgibt.

Wie man sieht, steht hinter diesem Widget-Schema nicht viel Code. Es werden größtenteils native ZF-Funktionen verwendet und kann daher leicht implementiert werden.
Für Ideen, wie man das System noch weiter verbessern kann, ist noch genug Platz in den Kommentaren 😉

2 Kommentare zu “Widgets mit dem Zend Framework

  1. Dein Artikel gefällt mir gut, besonders, weil das Beispiel sehr einfach und übersichtlich ist. Statt der Erweiterung über Vererbung, könnte man hier auch gut ein Controller-Plugin verwenden.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.