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
}
}
]]>