Zend Framework Tutorial Teil 3:
MVC Design Pattern und Zend_Controller
ACHTUNG:
Dieses Tutorial wird nicht mehr weitergeführt, da es auf ältere Versionen des Zend Frameworks aufbaut. Das neue Projekt ist hier:
Zend Framework Tutorial - Wir bauen ein Content Management System (CMS)
Nach der Einführung in das TravelloBlog Projekt im ersten Teil dieses Tutorials haben wir im zweiten Teil unser grundlegendes System aufgebaut, die Verzeichnisstruktur eingerichtet und eine erste rudimentäre Bootstrap Datei erstellt. Wer mochte, hat sich auch einen VirtualHost auf seinem Entwicklungsrechner eingerichtet. Wenn du die ersten beiden Teile noch nicht gelesen hast, hole dies bitte schnell nach.
In diesem dritten Teil gebe ich eine kurze Einführung in das Model-View-Controller Entwurfsmuster (neudeutsch auch Design Pattern). Mit diesem Wissen ausgerüstet werden wir unsere Anforderungen aus dem ersten Teil des Zend Framework Tutorials untersuchen und alle benötigten Controller und deren Aktionen (Actions) ermitteln. Danach erstellen wir gemeinsam unseren ersten Controller und die notwendigen Aktionen. Hierfür greifen wir auf die Zend Framework Komponente Zend_Controller zurück.
Wenn du über neue Tutorial Teile informiert werden möchtest, abonniere am besten den Feed dieses Blogs. Dann verpasst du garantiert keinen Teil des Tutorials. Es gibt auch Übersicht mit den bisher erschienen Teilen des Tutorials.
Inhaltsverzeichnis
- Model-View-Controller
- Zend_Controller
- Routing
- IndexController
- Download
- Zusammenfassung
- Changelog
- Navigation
- Kommentare
Model-View-Controller
Das Zend Framework bietet bereits alle Voraussetzungen, um ein Webprojekt nach dem Model-View-Controller Entwurfsmuster aufbauen zu können. Bei einer MVC Architektur wird die Anwendung in die drei wesentlichen Teilkomponenten Daten (Model), Präsentation (View) und Programmsteuerung (Controller) aufgeteilt.
Die Model Komponente ist hierbei für die Interaktion mit den Daten zuständig. Die Daten können aus verschiedenen Datenquellen stammen, z.B. aus einer MySQL oder SQLite Datenbank, aus XML Dateien oder einem beliebigen anderen Dateiformat oder über einen Webservice per XML-RPC oder SOAP von einem entfernten Webserver. Das Model liest die Daten aus der Datenquelle und gibt die gelesenen Daten an den Controller zurück. Das Model erhält aber auch Daten vom Controller und "speichert" sie in der Datenquelle ab.
Die View Komponente ist für die Präsentation der Daten zuständig. Bei einer Webanwendung ist dies in der Regel ein HTML Template, es kann aber auch eine XML Datei, ein RSS Feed oder eine WML Seite ausgegeben werden. Die View Komponente erhält die zu präsentierenden Daten vom Controller und sollte niemals direkt mit der Model Komponente interagieren. In einem View sollte nur Präsentationslogik (z.B. Schleifdurchläufe für die Darstellung von Listen oder einfache Fallentscheidungen für eine Farbwahl) enthalten sein und keine Geschäftslogik (z.B. Umrechnung von Währungskursen oder Verarbeitung von Eingabedaten). Die Verarbeitung der Geschäftslogik bleibt ausschließlich der Controller Komponente vorenthalten.
Die Controller Komponente ist dafür zuständig, zwischen den anderen beiden Komponenten zu vermitteln. In der Regel wird bei einer Anfrage an einen Webserver ermittelt, welcher Controller für die Verarbeitung der Anfrage zuständig ist. Wenn nötig, ruft der Controller bei der zuständigen Model Komponente die erforderlichen Daten ab, bereitet sie auf und übergibt sie an die zuständige View Komponente, welche die Daten darstellt. Der Controller kann bei einer Anfrage aber auch nur mit der View Komponente interagieren, wenn keine Daten gelesen oder geschrieben werden müssen. Genauso gut kann der Controller bei einer Anfrage aber auch nur mit der entsprechenden Model Komponente interagieren, wenn nach der Verarbeitung der Daten keine Ausgabe erforderlich ist.
Zend_Controller
Nach der theoretischen Einführung in das MVC-Konzept und der Ermittlung aller benötigten Controller und Aktionen gibt es nun endlich Butter bei die Fische. Mit Hilfe der Zend_Controller Komponente schreiben wir unsere erste Controller Klasse. Für einen Überblick empfehle ich die Lektüre des Zend Framework Manuals zur Zend_Controller Komponente.
Im Zend Framework wird ein Controller durch eine Klasse repräsentiert, die von der abstrakten Klasse Zend_Controller_Action abgeleitet werden muss. Zend_Controller_Action stellt einige Methoden für Redirects auf andere Seiten, das Weiterleiten zu anderen Controllern und Aktionen sowie das Bereitstellen von Parametern aus der angeforderten URL bereit.
Unsere Controller Klasse muss mit dem Namen des Controllers starten und auf "Controller" enden, wobei der Name mit einem Großbuchstaben beginnen muss. Für unser TravelloBlog würden wir z.B. folgende Controller Namen vergeben:
- IndexController
- ErrorController
- UserController
- ArticleController
- CommentController
- usw. usw.
Die Controller Klassen müssen genauso benannt werden und werden nur um die Dateiendung ".php" ergänzt. Alle Controller Klassen werden dann in einem Verzeichnis abgelegt. Wie du sicher schon vermutest, ist dies in unserem Fall das Verzeichnis "/travelloblog/application/controllers".
Die Aktionen eines Controllers müssen als öffentliche Methoden (public) deklariert werden. Sie müssen mit einem Kleinbuchstaben beginnen und auf "Action" enden. Durch das Routing weiß Zend_Controller dann, welche Controller Klasse und welche Action Methode aufgerufen werden muss. Dazu gleich mehr.
Die abstrakte Klasse Zend_Controller_Action, von der wir unsere Controller Klassen ableiten, setzt zwingend das Vorhandensein einer Methode mit Namen "indexAction" voraus. Diese Methode wird immer dann aufgerufen, wenn keine auszuführende Aktion für einen Controller ermittelt werden konnte.
Routing
Der erste Teil einer URL wird auf einen Controller und der zweite Teil auf die Aktion des Controllers abgebildet.
Ist weder Controller noch Aktion angegeben, wird per Default die Methode IndexController::indexAction() aufgerufen.
Ist zwar ein Controller aber keine Aktion angegeben, wird die Methode indexAction() in diesem Controller aufgerufen.
Hier nochmals, was wir im vorherigen Absatz geschrieben haben:
Die abstrakte Klasse Zend_Controller_Action, [...], setzt zwingend das Vorhandensein einer Methode mit Namen "indexAction" voraus. Diese Methode wird immer dann aufgerufen, wenn keine auszuführende Aktion für einen Controller ermittelt werden konnte.
Fehlt die Methode "indexAction" in einem Controller und dieser wird ohne Angabe einer Action Methode aufgerufen, gibt es einen Fehler und das Programm stoppt.
Lies dir das nochmal und eventuell nochmals durch!
Es ist wichtig, dass du dieses grundsätzliche Routing verstehst!!!
Hier einige Beispiel, wie das Routing per Default erfolgt:
| Adresse | Routing auf |
|---|---|
| http://travelloblog/ | IndexController::indexAction() |
| http://travelloblog/index/add | IndexController::addAction() |
| http://travelloblog/user | UserController::indexAction() |
| http://travelloblog/user/edit | UserController::editAction() |
| http://travelloblog/article/delete | ArticleController::deleteAction() |
IndexController
Damit du auch siehst, wie das Routing in der Realität funktioniert (oder auch nicht), probieren wir das jetzt einfach mal aus:
Gib bitte in deinem Browser zunächst einmal ein: "http://localhost/travelloblog/public/".
Du wirst die Eröffnungsseite sehen, die durch Verwendung von Zend_Tool erstellt worden ist.
Da weder Controller noch Aktion angegeben wurde, werden welcher Controller und welche Methode per Default verwendet?
Genau, der IndexController und die indexAction.
Was passiert nun, wenn eine der erwarteten Komponenten nicht vorhanden ist? Es gibt eine Fehlermeldung. Und wie das ausschaut, sehen wir uns jetzt einmal an.
Als erstes gehe bitte in das Verzeichnis "/travelloblog/application/controllers" und benenne die Datei "IndexController.php" um in z.B. "IndexController_.php"
Wenn du jetzt in deinem Browser wieder "http://localhost/travelloblog/public/" aufrufst, kommt folgende Fehlermeldung:
An error occurred
Page not found
Exception information:
Message: Invalid controller specified (index)
Stack trace:
[...]
Was sagt uns diese Fehlermeldung?
Es wurde ein ungültiger Controller angegeben (index[Controller]).
Wir haben keinen Controller angegeben, also wird der IndexController verwenet. Dieser wurde nicht gefunden (wir haben ihn ja umbenannt) und das erzeugt dann diese Fehlermeldung.
Benenne den IndexController bitte wieder um in "IndexController.php" und öffne die Datei.
Dann kommentiere die indexAction Methode aus und speichere die Datei:
-
<?php
-
-
class IndexController extends Zend_Controller_Action
-
{
-
-
public function init()
-
{
-
/* Initialize action controller here */
-
}
-
/*
-
public function indexAction()
-
{
-
// action body
-
}
-
*/
-
}
Rufe jetzt in deinem Browser wiederum "http://localhost/travelloblog/public/" auf. Diesmal bekommst du die Fehlermeldung
[...]
Message: Action "index" does not exist and was not trapped in __call()
[...]
die uns sagt, dass die Action Methode "index" (indexAction) nicht vorhanden ist.
Du erinnerst dich: Wird keine Aktionsmethode angegeben, wird die indexAction Methode per Default verwendet. Ist diese nicht vorhanden, erzeugt dies einen Fehler.
Die gleiche Fehlermeldung bekommst du übrigends, wenn du dich nicht an die korrekte Schreibweise hältst und z.B. "IndexAction" schreibst, anstatt "indexAction".
Entferne jetzt bitte wieder die Auskommentierung der indexAction, damit wieder alles einwandfrei funktioniert.
Du wirst dich mittlerweile vielleicht schon gefragt haben, wo die Datei mit dem HTML-Code versteckt ist.
Gehe dazu bitte in das Verzeichnis "/travelloblog/application/views/scripts". Hier findest du alle Dateien, die für die HTML-Ausgabe zuständig sind.
Zunächst siehst du aber nur zwei weitere Verzeichnisse: "error" und "index".
Hmmmm, kommen dir die Namen bekannt vor?
Na klar, wir haben ja einen ErrorController und einen IndexController.
Das kann doch kein Zufall sein, oder?
Nein, ist es natürlich nicht. Für jeden Controller muss ein Verzeichnis mit Namen des Controllers angelegt werden. Schau mal in das index-Verzeichnis. Dort ist die Datei "index.phtml". Und in dieser Datei ist der ganze HTML-Code drin. Benenne nun spaßeshalber die Datei "index.phtml um z.B. in "index_.phtml" und schau dir die Fehlermeldung an:
[...]
Message: script 'index/index.phtml' not found in path (C:\xampp\htdocs\travelloblog\application\views\scripts\)
[...]
Also: Der IndexController erwartet die Dateien, die über seine Methoden aufgerufen werden, im Verzeichnis "/views/scripts/index". Die indexAction Methode erwartet eine Datei mit dem Namen "index.phtml".
Mehr zu der Verzeichnis-/Dateistruktur im nächsten Teil.
Download
Der aktuelle Stand des Tutorials nach diesem zweiten Teil kann auch herunter geladen werden.
So lange das Tutorial noch nicht komplett auf die Version ab 1.8 umgeschrieben ist, werden die Sourcen für beide Versionen angeboten:
- Source Zend Framework Tutorial - Teil 3 - ZF ab v1.8 - Keine Änderung
- Source Zend Framework Tutorial - Teil 3 - ZF bis v1.7.8
Die Zip Datei enthält nicht die Bibliotheken (libraries) der aktuellen Version des Zend Frameworks. Die musst du bitte selber in das entsprechende Verzeichnis kopieren.
Zusammenfassung
In diesem dritten Teil meines Zend Framework Tutorials habe ich kurz das Model-View-Controller Konzept erläutert. Nach einer Einführung in die Zend_Controller Komponente haben wir den IndexController erstellt und erfahren, wie das Routing von URLs auf die Controller und Aktionsmethoden funktioniert.
Im nächsten Teil dieses Tutorials lernen wir die verschiedenen Arten, Komponenten anzulegen und beschäftigen uns intensiv mit Zend_Tool.
Fragen, Probleme und Anregungen bitte nicht per E-Mail senden, sondern hier in die Kommentare stellen. Dann haben alle etwas davon.
Changelog
- 30.09.2009 - Anpassung an Version 1.8 und höher
Navigation
- Zend Framework Tutorial Übersicht
- Zurück zu Teil 2: Systemaufbau und Erstellung des ersten Projekts
- Weiter zu Teil 4: Zend_Controller, Zend_View und Zend_Tool

Sonntag, 1. März 2009 20:41
Gut!
Donnerstag, 28. Mai 2009 20:18
Hallo,
diesen Fehler bekomme ich am Ende dieses Turorials.
Folgender Fehler ist aufgetreten:
Invalid controller specified (dlrg24h)
Stack Trace:
#0 C:\xampp\htdocs\dlrg24h\library\Zend\Controller\Front.php(936): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http))
#1 C:\xampp\htdocs\dlrg24h\application\bootstrap.php(29): Zend_Controller_Front->dispatch()
#2 C:\xampp\htdocs\dlrg24h\public\index.php(2): require(‘C:\xampp\htdocs…’)
#3 {main}
Gelöst hab ich es über folgende Zeile:
$frontController->setParam(‘useDefaultControllerAlways’, true);
Woran kann es liegen? Verwende 1.8.1
Samstag, 30. Mai 2009 19:36
durch den geänderten Bootstrap ab Version 1.8 passen die Eintragungen nicht mehr so ganz.
Da das Tutorial noch nicht auf >= 1.8 angepasst ist, kommt es zu Problemen.
Ich hoffe, ich schaffe die Anpassungen über die Feiertage,
Montag, 1. Juni 2009 23:17
hey super tutorial bis jetzt.
ich hab nur leider das gleiche problem. zumindest wenn ich das ganze über http://localhost/travelloblog/public/” aufrufe.
über den virtuellen host klappts. da bekomm ich die index.phtml.
was mach ich falsch.
Dienstag, 2. Juni 2009 22:45
ich kann mich nur wiederholen:
Sobald es auf die Version 1.8 angepasst ist, sollte auch alles wieder klappen.
Der Anfang ist bereits gemacht, aber eben noch nicht alles.
Dienstag, 9. Juni 2009 11:27
Moin,
ich bin auch gerade eben über das Problem mit dem invalid controller gestolpert.
Wenn man allerdings einen Standardcontroller definiert klapppt alles wunderbar und er schmeißt keine Exception:
In Zeile 19 einfach folgende Zeile einfügen:
$frontController->setParam(‘useDefaultControllerAlways’, true);
Mittwoch, 10. Juni 2009 10:39
Auch hier meine Erfahrung was man mit Version 1.8.2 im Unterschied zum hier geschriebenen tun muss:
Nichts!!!
Das ist das tolle am Zend_Tool: Bei Erstellung des Projektes wurde der IndexController bereits erstellt und das Verzeichnis wird automatisch als ControllerDirectory gesetzt. Aich eine View existiert schon – die sieht etwas anders aus, kann man aber so lassen und ebenfalls aufrufen.
Dienstag, 29. September 2009 14:30
Hallo, habe alles wie beschrieben gemacht, nur mit dem Framework 1.9.2. Bekomme jetzt folgende Fehlermeldung:
Fatal error: Uncaught exception ‘Zend_Application_Exception’ with message ‘Bootstrap class not found’ in C:\xampp\php\PEAR\Zend\Application.php:292 Stack trace: #0 C:\xampp\php\PEAR\Zend\Application.php(156): Zend_Application->setBootstrap(‘C:\xampp\htdocs…’, ‘Bootstrap’) #1 C:\xampp\php\PEAR\Zend\Application.php(85): Zend_Application->setOptions(Array) #2 C:\xampp\htdocs\ipa\application\run_app.php(24): Zend_Application->__construct(‘development’, ‘C:\xampp\htdocs…’) #3 C:\xampp\htdocs\ipa\public\index.php(3): require(‘C:\xampp\htdocs…’) #4 {main} thrown in C:\xampp\php\PEAR\Zend\Application.php on line 292
Hoffe mir kann jemand helfen…
Danke
Samstag, 12. Juni 2010 18:01
Ich bin dir so dankbar
Endlich funktioniert alles
jippie
@Christos
Hast du wohlmgl die Bootstrap.php enfernt oder unbenannt.
Du musst die index.php kopiereun und in den app ordner packen und dann diese umschreiben in run_app.php grüße
Dienstag, 10. August 2010 14:57
Huhu,
bin gerade am Punkt IndexController angekommen und habe den Fehler simmuliert.
Ich erhalte leider nur Meldung:
“An error occurred
Page not found”
ohne PHP Fehlerausgabe. Weis vielleicht Jemand wieso, Ideen wie ich es aktivieren kann?
Dankeschön
Woy
Montag, 30. August 2010 22:38
So wie WoY an meinem Geburtstag ( 10.August
) schon erwähnt hat, habe auch ich das Problem, dass bei mir nur:
An error occured
Application error
kommt. Aber keinerlei andere Fehlermeldung…
Was ist da los??? Bin echt ratlos! in der php.ini ist Fehlerausgabe aktiviert…
Freitag, 1. Oktober 2010 11:39
Das kann daran liegen das die Exceptions bei euch ausgestellt sind.
Das könnte daran liegen das die application.ini geändert wurde. resources.frontController.params.displayExceptions steht dann sicherlich auf o anstatt auf 1.
in der production Umgebung ist dies auch richtig, nur unter development sollte dieser Wert überschreiben werden.
MFG Lars
Donnerstag, 14. Juli 2011 5:53
Bisher ein wunderbares Tutorial, gefällt mir sehr!
Samstag, 6. August 2011 19:21
Hi,
An error occured
Application error
bei mir kommt nicht mal das wenn ich den IndexController umbenenne, es kommt lediglich eine weißte seite. Habe alle Werte in der application.ini die mit fehlern zu tun haben auf 1 gesetzt. dann bekomm ich:
Fatal error: Uncaught exception ‘Zend_Controller_Response_Exception’ with message ‘Cannot send headers; headers already sent in C:\xampp\htdocs\projekt\vermittlung\public\index.php, line 1′ in C:\xampp\htdocs\projekt\vermittlung\library\Zend\Controller\Response\Abstract.php:323 Stack trace: #0 C:\xampp\htdocs\projekt\vermittlung\library\Zend\Controller\Response\Abstract.php(341): Zend_Controller_Response_Abstract->canSendHeaders(true) #1 C:\xampp\htdocs\projekt\vermittlung\library\Zend\Controller\Response\Abstract.php(768): Zend_Controller_Response_Abstract->sendHeaders() #2 C:\xampp\htdocs\projekt\vermittlung\library\Zend\Controller\Front.php(992): Zend_Controller_Response_Abstract->sendResponse() #3 C:\xampp\htdocs\projekt\vermittlung\library\Zend\Application\Bootstrap\Bootstrap.php(97): Zend_Controller_Front->dispatch() #4 C:\xampp\htdocs\projekt\vermittlung\library\Zend\Application.php(366): Zend_Application_Bootstrap_Bootstrap->run() #5 C:\xampp\htdocs\projekt\vermittlung\application\run_app.php(26): Zend_Application in C:\xampp\htdocs\projekt\vermittlung\library\Zend\Controller\Response\Abstract.php on line 323
wo hab ich denn da den fehler? (btw, habe das projekt “vermittlung” genannt, das ist mir schon klar
)
bitte um einen Tipp!
Samstag, 6. August 2011 19:28
ok gelöst – aufpassen dass in der index.php keine whitespaces vor dem <php stehen