ViewRendererEinführung
Der ViewRenderer Helfer wurde designt um die folgenden Ziele erfüllen:
Entfernen der Notwendigkeit View Objekte innerhalb der Kontroller zu
instanzieren; View Objekte werden automatisch mit dem Kontroller registriert.
Automatisch View Skript, Helfer und Filter Pfade setzen basierend auf dem
aktuellen Modul, und den aktuellen Modulnamen automatisch als Klassenprefix für
Helfer und Filterklassen assoziieren.
Ein global vorhandenes View Objekt für alle bearbeitenden Kontroller und
Aktionen erstellen.
Dem Entwickler erlauben das Standard View Rendering Optionen für alle Kontroller
gesetzt werden.
Die Fähigkeit hinzufügen das ein View Skript ohne Intervention automatisch
gerendert wird.
Dem Entwickler erlauben seine eigenen Spezifikationen, für den View Basisnamen
und für View Skriptpfade, zu erstellen.
Wenn man ein _forward(), eine Umleitung, oder ein render
manuell durchführt, wird kein automatisches rendern erfolgen, da man beim Ausführen
von jeder dieser Aktionen dem ViewRenderer mitteilt das man seine
eigene Ausgabe durchführen will.
Der ViewRenderer ist standardmäßig aktiviert. Man kann Ihn über den
Parameter noViewRenderer des Frontkontrollers deaktivieren
($front->setParam('noViewRenderer', true)) oder den Helfer vom Helfer
Broker Stack entfernen
(Zend_Controller_Action_HelperBroker::removeHelper('viewRenderer')).
Wenn man Einstellungen vom ViewRenderer vor der Ausführung des Front
Kontrollers ändern will, kann das auf zwei Wegen getan werden:
Instanzieren und Registrieren eines eigenen ViewRenderer
Objekts und dieses an den Helfer Broker übergeben:
setView($view)
->setViewSuffix('php');
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
]]>
Initialisieren und/oder empfangen eines ViewRenderer Objekts
auf Wunsch über den Helfer Broker:
setView($view)
->setViewSuffix('php');
]]>API
In seiner einfachsten Verwendung, kann der ViewRenderer ganz einfach
instanziert und an den Aktion Helfer Broker übergeben werden. Der einfachste Weg Ihn auf
einmal zu Instanzieren und Registrieren ist es, die Methode
getStaticHelper() des Helfer Brokers zu verwenden:
Das erste Mal wenn ein Aktion Kontroller instanziert wird, triggert er den
ViewRenderer ein View Objekt zu instanzieren. Jedes Mal wen ein Kontroller
Instanziert wird, wird die init() Methode des ViewRenderer's
aufgerufen, was dazu führt das er die view Eigenschaft des Aktion Kontrollers setzt, und
addScriptPath(), mit einem Pfad relativ zum aktuellen Modul, aufruft; das
wird mit einem Klassenprefix aufgerufen der nach dem aktuellen Modul benannt ist, was
effektiv für alle Helfer und Filterklassen die im Modul definiert werden den Namensraum
setzt.
Jedes Mal wenn postDispatch() aufgerufen wird, ruft dieses
render() für die aktuelle Aktion auf.
Als Beispiel kann die folgende Klasse angenommen werden:
view->foo = 'bar';
}
}
...
// In einem der View Sktipte:
$this->foo(); // Foo_View_Helper_Foo::foo() aufrufen
]]>
Der ViewRenderer definiert auch eine Anzahl von Zugriffspunkten im das
Setzen und Empfangen von View Optionen zu erlauben:
setView($view) erlaubt das Setzen des View Objektes für den
ViewRenderer. Er wird als öffentliche Klasseneigenschaft
$view gesetzt.
setNeverRender($flag = true) kann verwendet werden um das
automatische rendern global ein- oder auszuschalten, z.B. für alle Kontroller.
Wenn er auf true gesetzt wird, ruft postDispatch() nicht
automatisch render() im aktuellen Kontroller auf.
getNeverRender() empfängt den aktuellen Wert.
setNoRender($flag = true) kann verwendet werden um das automatische
rendern ein- oder auszuschalten. Wenn er auf true gesetzt wird, wird
postDispatch()render() im aktuellen Kontroller nicht
automatisch aufrufen. Diese Einstellung wird jedesmal zurückgesetzt wenn
preDispatch() aufgerufen wird (z.B. muß dieses Flag für jeden
Kontroller gesetzt werden für den das automatische rendern nicht automatisch
stattfinden soll). getNoRender() empfängt den aktuellen Wert.
setNoController($flag = true) kann verwendet werden um
render() zu sagen das für Aktion Skripts nicht in einem
Unterverzeichnis gesucht werden soll das nach dem Kontroller benannt ist (was
das Standardverhalten ist). getNoController() empfängt den
aktuellen Wert.
setNeverController($flag = true) ist analog zu
setNoController(), arbeitet aber auf einem globalen Leven -- z.B.
wird es nicht für jede ausgeführte Aktion resetiert.
getNeverController() empfängt den aktuellen Wert.
setScriptAction($name) kann verwendet werden um das Aktion Skript
zu spezifizieren das gerendert werden soll. $name sollte der
Name des Skripts sein, ohne den Datei Suffix (und ohne das Kontroller
Unterverzeichnis, ausser wenn noController eingeschaltet wurde).
Wenn nicht spezifiziert, wird nach einem View Skript gesucht das nach der Aktion
in Anfrage Objekt benannt ist. getScriptAction() empfängt den
aktuellen Wert.
setResponseSegment($name) kann verwendet werden um zu spezifizieren
in welches Segment das nach einem Antwort Objekt benannt ist, gerendert werden
soll. Wenn nicht spezifiziert, wird in das Standard Segment gerendert.
getResponseSegment() empfängt den aktuellen Wert.
initView($path, $prefix, $options) kann aufgerufen werden um den
Basis View Pfad, den Klassenprefix für Helfer, Filter Skripts und
ViewRenderer Optionen zu spezifizieren. Es kann eines der folgenden
Flags übergeben werden: neverRender, noRender,
noController, scriptAction, und
responseSegment.
setRender($action = null, $name = null, $noController = false)
erlaubt es scriptAction, responseSegment, oder
noController in einem Schritt zu übergeben. direct()
ist ein Alias für diese Methode, und erlaubt es diese Methode einfach vom
eigenen Kontroller aus aufzurufen:
_helper->viewRenderer('foo');
// Rendert form.phtml zum 'html' Antwort Segment, ohne einen Kontroller aus dem
// Unterverzeichnis des View Skripts zu verwenden:
$this->_helper->viewRenderer('form', 'html', true);
]]>setRender() und direct() stellen das View Sktript
nicht dar, sondern setzen Hinweise die postDispatch() und
render() dann verwenden wenn die View dargestellt wird.
Der Constructor erlaubt es optional das View Objekt und ViewRenderer
Optionen zu übergeben; er akzeptiert die gleichen Flags wie initView():
'UTF-8'));
$options = array('noController' => true, 'neverRender' => true);
$viewRenderer =
new Zend_Controller_Action_Helper_ViewRenderer($view, $options);
]]>
Es gibt einige zusätzliche Methoden für das individualisieren von Pfadspezifikationen
die für das Herausfinden des Basis View Pfades verwendet werden der dem View Objekt
hinzugefügt wird, und den View Skript Pfad der verwendet wird wenn das View Skript zu
dem gerendert werden soll automatisch herausgefunden wird. Diese Methoden nehmen alle
ein oder mehrere der folgenden Platzhalter:
:moduleDir zeigt auf das aktuelle Modul Basisverzeichnis (von der
Konvention her das Elternverzeicnis des Kontroller Verzeichnisses des Moduls).
:module zeigt auf den aktuellen Modulnamen.
:controller zeigt auf den aktuellen Kontrollernamen.
:action zeigt auf den aktuellen Aktionsnamen.
:suffix zeigt auf das aktuelle Suffix des View Skripts (welcher
über setViewSuffix() gesetzt werden kann).
Die Methoden für das kontrollieren der Pfad Spezifikationen sind:
setViewBasePathSpec($spec) erlaubt die Änderung der Pfad
Spezifikation die verwendet wird um den Basispfad herauszufinden zu dem das
View Objekt hinzugefügt werden soll. Die Standardspezifikation ist
:moduleDir/views. Die aktuelle Spezifikation kann jederzeit
durch Verwenden von getViewBasePathSpec() erhalten werden.
setViewScriptPathSpec($spec) erlaubt die Änderung der Pfad
Spezifikation die verwendet wird um den Pfad zu einem individuellen View Skript
herauszufinden (ohne den Basis View Skript Pfad). Die Standard Spezifikation ist
:controller/:action.:suffix. Die aktuelle Spezifikation kann
jederzeit durch Verwenden von getViewScriptPathSpec() erhalten
werden.
setViewScriptPathNoControllerSpec($spec) erlaubt die Änderung der
Pfad Spezifkiation die verwendet wird um den Pfad zu einem individuellen View
Skript herauszufinden wenn noController aktiv ist (ohne den Basis
View Skript Pfad). Die Standard Spezifikation ist :action.:suffix.
Die aktuelle Spezikifation kann jederzeit durch Verwenden von
getViewScriptPathNoControllerSpec() erhalten werden.
Für eine feinkörnige Kontrolle über Pfadspezifikationen kann
Zend_Filter_Inflector verwendet werden.
Im Hintergrund verwendet der ViewRenderer einen Inflector um bereits
Abstimmungen am Pfad durchzuführen. Um auf dem Inflector einzuwirken, damit entweder
ein eigener für die Verwendung gesetzt wird, oder um den Standard Inflector zu
verändern, können die folgenden Methoden verwendet werden:
getInflector() empfängt den Inflector. Wenn bis dahin keiner im
ViewRenderer existiert, wird dieser, anhand der Verwendung der
Standard Regeln, erstellt.
Standardmäßig verwendet dieser statische Referenzregeln für das Suffix und
Modulverzeichnis, sowie ein statisches Ziel; das erlaubt verschiedenen
ViewRenderer Eigenschaften den Inflector dynamisch zu ändern.
setInflector($inflector, $reference) erlaubt das Setzen eines
eigenen Inflectors für die Verwendung mit dem ViewRenderer. Wenn
$reference true ist, setzt dieser das Suffix und
Modulverzeichnis als statische Referenz zu ViewRenderer
Eigenschaften, genauso wie das Ziel.
Standard Konventionen für das Eruieren
Der ViewRenderer führt einige Pfad Normalisierungen durch um das
Eruieren von View Skripten einfacher zu machen. Die Standardregeln sind wie folgt:
:module: MixedCase und camelCaseWörter werden durch
Bindestriche getrennt, und der komplette String wird auf
Kleinschreibung geändert. z.B.: "FooBarBaz" wird "foo-bar-baz".
Intern verwendet der Inflector die Filter
Zend_Filter_Word_CamelCaseToDash und
Zend_Filter_StringToLower.
:controller: MixedCase und camelCaseWörter werden durch
Bindestriche getrennt; Unterstriche werden in Verzeichnistrennzeichen
konvertiert, und der komplette String wird auf Kleinschreibung geändert.
Beispiele: "FooBar" wird "foo-bar"; "FooBar_Admin" wird "foo-bar/admin".
Intern verwendet der Inflector die Filter
Zend_Filter_Word_CamelCaseToDash,
Zend_Filter_Word_UnderscoreToSeparator und
Zend_Filter_StringToLower.
:action: MixedCase und camelCaseWörter werden durch
Bindestriche getrennt; nicht-anphanummerische Zeichen werden zu
Bindestrichen übersetzt, und der komplette String wird auf
Kleinschreibung geändert. Beispiele: "fooBar" wird "foo-bar"; "foo-barBaz"
wird "foo-bar-baz".
Intern verwendet der Inflector die Filter
Zend_Filter_Word_CamelCaseToDash,
Zend_Filter_PregReplace und
Zend_Filter_StringToLower.
Die letzten Teile in der ViewRenderer API sind die Methoden für das
aktuelle herausfinden von View Skript Pfaden und Rendern von Views. Diese beinhalten:
renderScript($script, $name) erlaubt es ein Skript mit einem selbst
spezifizierten Pfad zu rendern, optional zu einem benannten Pfad Segment. Wenn
diese Methode verwendet wird, ermittelt der ViewRenderer nicht
automatisch den Skriptnamen sondern übergibt das $script
Argument direkt der render() Methode des View Objekts.
Sobald die View zum Antwort Objekt gerendert wurde, setzt diese
noRender um irrtümliches mehrfaches rendern zum selben View Skript
zu verhindern.
Standardmäßig handelt
Zend_Controller_Action::renderScript() in Vertretung
zur renderScript() Methode des ViewRenderer's.
getViewScript($action, $vars) erstellt den Pfad zu einem View
Skript das auf einer Aktion basiert die übergeben wird, und/oder allen Variablen
die in $vars übergeben werden. Schlüssel für dieses Array
können jede der Pfad Spezifikations Schhüssel enthalten ('moduleDir', 'module',
'controller', 'action', und 'suffix'). Jede übergebene Variable wird verwendet;
andernfalls werden Werte die auf der aktuellen Anfrage basieren angewendet.
getViewScript() verwendet entweder viewScriptPathSpec
oder viewScriptPathNoControllerSpec basierend auf den Einstellungen
des noController Flags.
Wortbegrenzer die in Modul-, Kontroller- oder Aktionsnamen vorkommen werden mit
Bindestrichen ('-') ersetzt. Deshalb resultiert, wenn der Kontrollername
'foo.bar' und die Aktion 'baz:bat' ist, die Verwendung der standard Pfad
Spezifikation einen View Skript Pfad von 'foo-bar/baz-bat.phtml'.
Standardmäßig handelt
Zend_Controller_Action::getViewScript() in Vertretung
zur getViewScript() Methode des ViewRenderer's.
render($action, $name, $noController) prüft zuerst ob entweder
$name oder $noController übergeben wurde,
und wenn dem so ist, wird das betreffende Flag (respektive responseSegment und
noController) im ViewRenderer gesetzt. Dann übergibt er das
$action Argument, wenn vorhanden, an
getViewScript(). Am Ende wird der berechnete View Skript Pfad an
renderScript() übergeben.
Achtung vor den Nebeneffekten bei der Verwendung von render(): Die Werte die
für den Anwort Segment Namen und für das noController Flag übergeben werden
sind im Objekt dauerhaft. Zusätzlich wird noRender gesetzt nachdem das
rendern fertig ist.
Standardmäßig handelt
Zend_Controller_Action::render() in Vertretung zur
render() Methode des ViewRenderer's.
renderBySpec($action, $vars, $name) erlaubt es Pfad Spezifikations
Variablen zu übergeben um den View Skript Pfad zu ermitteln der erstellt werden
soll. Es übergibt $action und $vars an
getScriptPath() und übergibt anschließend den resultierenden Skript
Pfad und $name an renderScript().
Grundsätzliches Beispiel der VerwendungGrundsätzliche Verwendung
Am einfachsten, wird einfach der ViewRenderer Helfer mit dem Helfer
Broker in der eigenen Bootstrap Datei, initialisiert und registriert, und
anschließend die Variablen in den Aktion Methoden gesetzt.
view->foo = 'bar';
}
// Rendert nichts da zu einer anderen Aktion weitergeleitet wird;
// die neue Aktion wird jegliches rendern durchführen
public function bazAction()
{
$this->_forward('index');
}
// Rendert nichts da zu einer anderen Lokation weitergeleitet wird
public function batAction()
{
$this->_redirect('/index');
}
}
]]>Benamungs Konventionen: Wort Begrenzer in Kontroller- und Aktionnamen
Wenn der Kontroller- oder Aktionsname aus mehreren Wörtern aufgebaut ist, müssen
diese, da der Dispatcher das benötigt, seperiert sein durch die URL nach
spezifischem Pfad und Wort Begrenzer Zeichen. Der ViewRenderer ersetzt
jeden Pfad Begrenzer den er im Kontrollernamen findet mit einem aktuellen Pfad
Begrenzer ('/'), und jeden Wort Begrenzer der gefunden wird mit einem Bindestrich
('-') wenn Pfade erstellt werden. Deshalb würde ein Aufruf der Aktion
/foo.bar/baz.bat zu FooBarController::bazBatAction() in
FooBarControll.php weiterleiten was wiederum foo-bar/baz-bat.phtml
rendern würde; ein Aufruf der Aktion /bar_baz/baz-bat für dazu das
Bar_BazController::bazBatAction() in Bar/BazController.php
dispatched wird (betrachte die Separation des Pfades) und
bar/baz/baz-bat.phtml gerendert wird.
Es ist zu beachten das im zweiten Beispiel, das Modul noch immer das Standardmodul
ist, aber das der Kontroller, wegen der Existenz eines Pfad Separators, den Namen
Bar_BazController in Bar/BazController.php empfängt. Der
ViewRenderer emuliert die Kontroller Verzeichnis Hierarchie.
Automatisches rendern ausschalten
Für einige Aktionen oder Kontroller, kann es gewünscht sein das automatische Rendern
auszuschalten -- zum Beispiel, wenn eine andere Art von Ausgabe (XML, JSON, etc)
ausgegeben werden soll, oder wenn man einfach nichts ausgeben will. Es gibt zwei
Optionen: Alle Fälle von automatischem Rendern ausschalten
(setNeverRender()), oder dieses einfach für die aktuelle Aktion
ausschalten (setNoRender()).
_helper->viewRenderer->setNoRender();
}
}
// Bat Kontroller Klasse, Bar Modul:
class Bar_BatController extends Zend_Controller_Action
{
public function preDispatch()
{
// Die Aktionen dieses Kontroller nie automatisch Rendern
$this->_helper->viewRenderer->setNoRender();
}
}
]]>
In den meisten Fällen, macht es keinen Sinn das automatische Rendern global
auszuschalten (ala setNeverRender()), da das einzige das man dann vom
ViewRenderer erhält das automatische Setup des View Objekts ist.
Ein anderes View Skript auswählen
Einige Situationen erfordern das ein anderes Skript, als das nach der Aktion
benannte, ausgeführt wird. Zum Beispiel, wenn man einen Kontroller hat der Aktionen
sowohl hinzufügen als auch bearbeiten kann, und beide mit der selben 'form' View
angezeigt werden, aber mit unterschiedlichen Werten gesetzt werden. Der Skript Name
kann ganz einfach geändert werden. Entweder mit setScriptAction(),
setRender() oder durch Aufruf des Helfers als Methode, was wiederum
setRender() ausruft.
_helper->viewRenderer('form');
}
public function editAction()
{
// Rendert 'bar/form.phtml' statt 'bar/edit.phtml'
$this->_helper->viewRenderer->setScriptAction('form');
}
public function processAction()
{
// einige Prüfungen durchführen...
if (!$valid) {
// Rendert 'bar/form.phtml' statt 'bar/process.phtml'
$this->_helper->viewRenderer->setRender('form');
return;
}
// andernfalls die Bearbeitung weiter durchführen...
}
}
]]>Die resigstrierte View ändern
Was wenn ein View Objekt modifiziert werden soll -- zum Beispiel, die Helfer Pfade
ändern, oder die Kodierung? Das kann durch Modifikation des View Objekts, das im
Kontroller gesetzt ist, gemacht werden, oder durch herausnehmen des View Objekts aus
dem ViewRenderer; beide referenzieren auf das gleiche Objekt.
view->setEncoding('UTF-8');
}
public function bazAction()
{
// Das View Objekt erhalten, und den Kommentar Callback
// auf 'htmlspecialchars' setzen
$view = $this->_helper->viewRenderer->view;
$view->setEscape('htmlspecialchars');
}
}
]]>Erweiterte Beispiel der VerwendungDie Pfad Spezifikationen ändern
In einigen Fällen, kann man entscheiden das die standardmäßige Pfad Spezifikation
nicht den Notwendigkeiten der Seite entspricht. Zum Beispiel, wenn man einen
einzelnen Template Baum haben will zu dem man dann Zugriff für Entwickler geben kann
(das ist sehr typisch wenn man zum Beispiel Smarty verwendet). In solchen Fällen, kann
es gewünscht sein die Spezifkiation des View Basispfades hardkodiert zu erstellen
und eine alternative Spezifikation für die Pfade der Aktions View Skripte selbst zu
erstellen.
Für die Zwecke dieses Beispiels, nehmen wir an das der Basispfad zur View
'/opt/vendor/templates' sein soll, und das die View Skripte durch
':moduleDir/:controller/:action.:suffix' referenziert werden sollen; wenn das
noController Flag gesetzt wurde, soll aus dem Top Level statt aus einem
Unterverzeichnis gerendert werden (':action.:suffix'). Zuletzt soll 'tpl' als View
Skript Suffix für Dateinamen verwendet werden.
setViewBasePathSpec('/opt/vendor/templates')
->setViewScriptPathSpec(':module/:controller/:action.:suffix')
->setViewScriptPathNoControllerSpec(':action.:suffix')
->setViewSuffix('tpl');
Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
]]>Mehrfache View Skripte von der gleichen Aktion rendern
Manchmal, ist es notwendig mehrfache View Skripte von einer einzelnen Aktion zu
rendern. Das ist sehr geradlinig -- einfach mehrere Aufrufe zu render()
machen:
model das aktuelle Modell ist
$this->view->results =
$this->model->find($this->_getParam('query', '');
// render() handelt standardmäßig in Vertretung zum ViewRenderer
// Rendert zuerst die Such Form und anschließend die Ergebnisse
$this->render('form');
$this->render('results');
}
public function formAction()
{
// tue nichts; der ViewRenderer bearbeitet das View Skript automatisch
}
}
]]>