ViewRendererEinführung
Der ViewRenderer Helfer wurde designt um die folgenden Ziele
erfüllen:
Entfernen der Notwendigkeit View Objekte innerhalb der Controller zu
instanzieren; View Objekte werden automatisch mit dem Controller 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 Controller und
Aktionen erstellen.
Dem Entwickler erlauben das Standard View Rendering Optionen für alle Controller
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(),
redirect() oder 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 Frontcontrollers
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 Controllers ä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 Controller instanziert wird, triggert er den
ViewRenderer ein View Objekt zu instanzieren. Jedes Mal wenn ein
Controller Instanziert wird, wird die init() Methode des
ViewRenderer's aufgerufen, was dazu führt das er die view
Eigenschaft des Aktion Controllers 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
um 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
Controller. Wenn er auf TRUE gesetzt wird, ruft
postDispatch() nicht automatisch
render() im aktuellen Controller 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 Controller nicht automatisch aufrufen. Diese Einstellung wird
jedesmal zurückgesetzt wenn preDispatch() aufgerufen
wird (z.B. muß dieses Flag für jeden Controller 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 Controller benannt ist
(was das Standardverhalten ist). getNoController()
empfängt den aktuellen Wert.
setNeverController($flag = true) ist analog zu
setNoController(), arbeitet aber auf einem globalen
Level -- z.B. wird es nicht für jede ausgeführte Aktion zurückgesetzt.
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 Controller 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
Controller aus aufzurufen:
_helper->viewRenderer('foo');
// Rendert form.phtml zum 'html' Antwort Segment, ohne einen Controller 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 Controller Verzeichnisses des
Moduls).
:module zeigt auf den aktuellen Modulnamen.
:controller zeigt auf den aktuellen Controllernamen.
: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 $referenceTRUE 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 enthalten:
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-, Controller- oder Aktionsnamen vorkommen werden mit
Bindestrichen ('-') ersetzt. Deshalb resultiert, wenn der Controllername
'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 Controller- und Aktionnamen
Wenn der Controller- 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
Controllernamen 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 darstellen 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 Controller, wegen der Existenz eines Pfad Separators, den Namen
Bar_BazController in
Bar/BazController.php empfängt. Der ViewRenderer emuliert die
Controller Verzeichnis Hierarchie.
Automatisches rendern ausschalten
Für einige Aktionen oder Controller, 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 Controller Klasse, Bar Modul:
class Bar_BatController extends Zend_Controller_Action
{
public function preDispatch()
{
// Die Aktionen dieses Controller 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 Controller 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
Controller 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
}
}
]]>