Zend Framework Tutorial Teil 4: MVC Design Pattern und Zend_Db

Im dritten Teil des Zend Framework Tutorials haben wir das Model-View-Controller Entwurfsmuster kennen gelernt. Basierend auf der Komponente Zend_Controller haben wir dann unsere Controller Klassen für unser TravelloBlog erstellt. Wenn du die ersten drei Teile noch nicht gelesen hast, hole dies bitte schnell nach.

In diesem vierten Teil des Tutorials werden wir uns um die Model Komponente unseres Projektes kümmern. Zuerst werden wir auf Basis der Anforderungen aus dem ersten Teil unser Datenbankmodell entwickeln. Basierend auf der Einführung in das Model-View-Controller Konzept werden wir dann unsere Model Klassen erstellen und die Verwendung in den Aktionsmethoden unserer Controller Klassen einbinden. Hierbei lernen wir die Zend Framework Komponente Zend_Db und deren diversen Hilfsklassen kennen.

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.

Wichtig: Dieses Tutorial setzt die Zend Framework Preview Version 0.6.0 voraus und kann bei der Verwendung einer aktuelleren Version aus dem SVN unter Umständen nicht zu 100% funktionieren.

Inhaltsverzeichnis

Datenbankmodell

Unsere Datenbank werden wir in einer MySQL Datenbank ablegen. Jedoch sollte das zu erstellende Datenbankmodell auch in SQLite sowie anderen Datenbanken verwendet werden können.

Um unser Datenbankmodell erstellen zu können, wenden wir uns wieder den Anforderungen an unser TravelloBlog aus dem ersten Teil dieses Tutorials zu. Hilfreich ist dabei auch die Liste der Entitäten, die wir im dritten Teil des Tutorials ermittelt haben.

Für jede der ermittelten Entitäten würde es sich anbieten, eine eigene Datenbanktabelle zu erstellen. Die einzige Ausnahme ist die Entität "Suchindex", weil wir den Suchindex erst später mit Hilfe der Zend_Search Komponente anlegen werden und wir uns dann um die Datenstruktur kümmern können. Folglich erstellen wir für die restlichen fünf Entitäten jeweils eine Datenbanktabelle.

Um die Datenbanktabelle "user" für die Benutzerdaten nicht zu sehr aufzublähen, lagere ich das in Anforderung 2 geforderte Profil in eine eigene Datenbanktabelle aus. Zudem benötigen wir für die in Anforderung 4 geforderten Zuordnungen von beliebig vielen Kategorien bzw. Tags zu einem Beitrag noch zwei weitere Verknüpfungstabellen. Insgesamt kommen wir also vorerst auf acht Tabellen:

  • article
  • comment
  • tag
  • category
  • user
  • profile
  • art2tag (Verknüpfungstabelle zwischen article und tag)
  • art2cat (Verknüpfungstabelle zwischen article und category)

Anhand der weiteren Anforderungen ermitteln wir dann, welche Tabelle welche Felder oder Spalten benötigt. Diese ergänzen wir dann um weitere sinnvolle Felder. Insgesamt sieht unser Datenbankmodell dann wie folgt aus:

Datenbankmodell TravelloBlog

Hinweis

Erstellt habe ich das Datenbankmodell mit dem DBDesigner4, einer Software zum Modellieren von Datenbanken, die aktuell leider nicht mehr weiter entwickelt wird. Das Projekt wird aber von MySQL mit der MySQL Workbench fortgeführt, welche Bestandteil des MySQL GUI Tools Bundles ist. Leider ist die Workbench jedoch noch etwas fehlerbehaftet, so dass ich derzeit weiterhin mit DBDesigner4 arbeite.

In der Zip Datei, die du weiter unten downloaden kannst, ist ein MySQL Dump für die Tabellenstruktur enthalten. Ich habe den Dump noch um einige Beispieldaten angereichert, damit du beim Abfragen der Datenbank gleich etwas sehen kannst. Diesen Dump spielst du am besten in eine neue Datenbank ein. Ich habe meine der Einfachheit halber "travelloblog" benannt.

Zend_Db

Nun, wo die Datenbankstruktur steht und wir eine Datenbank angelegt und mit Daten befüllt haben, können wir endlich in die Zend_Db Komponente einsteigen. Die Zend_Db Komponente besteht derzeit (Version 0.6.0) aus sechs Teilkomponenten, die wir nun kurz vorstellen möchten.

Zend_Db_Adapter stellt die Datenbankabstraktionsschicht für das Zend Framework bereit und setzt auf die Erweiterung PDO auf, die seit PHP 5.1 fester Bestandteil von PHP ist. Zend_Db_Adapter ist für den Verbindungsaufbau zu einer Datenbank zuständig und stellt Funktionen für das Quoten von Parametern, für Transaktionen sowie für die Datenbankoperationen Einfügen (Insert), Aktualisieren (Update), Löschen (Delete) und Selektieren (Select) bereit.

Zend_Db_Profiler ist eine nützliche Klasse für das Analysieren von Datenbankoperationen. Es können Profile erstellt und anhand bestimmter Kriterien ausgewertet werden.

Zend_Db_Select ist ein Werkzeug, mit dem man datenbankunabhängige Select-Abfragen erstellen kann. Es können Spalten ausgewählt und Tabellen miteinander verbunden werden. Es können WHERE und HAVING Bedingungen, GROUP BY und ORDER BY Klauseln sowie LIMIT Begrenzungen zu einer Select-Abfrage hinzugefügt werden. Durch die Datenbankunabhängigkeit der Abfragen kann einfach zwischen den von Zend_Db unterstützen Datenbanken gewechselt werden.

Zend_Db_Table ist ein Tabellenmodul für das Zend Framework, welches die Struktur einer Datenbanktabelle analysieren kann und dich beim Ändern und Selektieren von Daten aus einer Datenbanktabelle unterstützt. Eine von Zend_Db_Table abgeleitete Klasse bietet Methoden für das Selektieren und Speichern von Daten, ohne dass man sich um den Aufbau der diversen Datenbankoperationen kümmern muss.

Zend_Db_Table_Row repräsentiert eine Zeile einer Datenbank. Wenn über Zend_Db_Table eine Select-Abfrage durchgeführt wurde, wird als Ergebnis eine Objektinstanz von Zend_Db_Table_Row zurückgeliefert, über das man sehr einfach auf die Werte dieses Datensatzes zugreifen, sie verändern und wieder speichern kann.

Zend_Db_Table_Rowset wiederum stellt eine Sammlung von Zend_Db_Table_Row Objekten bereit. Über diese Ergebnismenge kann iteriert werden, so dass man sich Schritt für Schritt durch die Zend_Db_Table_Row Objekte bewegen kann.

Im weiteren Verlauf gehe ich primär auf Zend_Db_Adapter, Zend_Db_Table, Zend_Db_Table_Row und Zend_Db_Table_Rowset ein. Für eine tiefergehende Lektüre zu den anderen Teilkomponenten von Zend_Db empfehle ich die Lektüre des Zend Framework Manuals.

Zend_Db_Adapter

Um überhaupt mit Hilfe des Zend Frameworks auf eine Datenbank zugreifen zu können, musst du zuerst eine Instanz von Zend_Db_Adapter erstellen. Hierfür öffne bitte die Datei "ArticleController.php" im Verzeichnis "/travelloblog/application/controllers" und ändere die Methode "indexAction" wie folgt ab:

PHP:
  1. <?php
  2. class ArticleController extends Zend_Controller_Action
  3. {
  4.     public function indexAction()
  5.     {
  6.         require_once 'Zend/Db.php';
  7.        
  8.         $params = array ('host'     => '127.0.0.1',
  9.                          'username' => 'root',
  10.                          'password' => '',
  11.                          'dbname'   => 'travelloblog');
  12.        
  13.         $db = Zend_Db::factory('PDO_MYSQL', $params);       
  14.     }
  15.  
  16.     [...]
  17. }
  18. ?>

Als erstes laden wir die Zend_Db Basisklasse. Danach erstellen wir ein Array mit den Zugangsdaten zu unserer MySQL Datenbank. Dort musst du natürlich deine eigenen Daten eintragen.

Als letztes rufen wir die statische Methode Zend_Db::factory auf und übergeben ihr zwei Parameter. Der erste Parameter ist der Name des Datenbankadapters, in unserem Fall wird PDO für MySQL verwendet. Neben PDO für MySQL stehen derzeit noch viele weitere Datenbankadapter bereit:

  • PDO für MySQL, MS SQL, PostgreSQL und SQLite
  • DB2
  • Oracle
  • mysqli

Um auf eine andere Datenbank als MySQL zugreifen zu können, muss lediglich der Name des Adapters im Aufruf von Zend_Db::factory ausgetauscht werden. Da die Verbindung zur Datenbank alleine noch keine Katze hinter dem Ofen hervor lockt, erweitern wir die "indexAction" Methode noch ein wenig mehr.

PHP:
  1. <?php
  2. class ArticleController extends Zend_Controller_Action
  3. {
  4.     public function indexAction()
  5.     {
  6.         require_once 'Zend/Db.php';
  7.        
  8.         $params = array ('host'     => '127.0.0.1',
  9.                          'username' => 'root',
  10.                          'password' => '',
  11.                          'dbname'   => 'travelloblog');
  12.        
  13.         $db = Zend_Db::factory('PDO_MYSQL', $params);       
  14.        
  15.         $result = $db->query('select * from article');
  16.        
  17.         $rows = $result->fetchAll();
  18.        
  19.         Zend::dump($rows);
  20.     }
  21.  
  22.     [...]
  23. }
  24. ?>

Wir senden über $db->query() eine Select-Abfrage ab, um die Tabelle "article" auszulesen. Dann holen wir uns per $result->fetchAll() die Ergebnisse und geben sie mit der nützlichen Methode Zend::dump() auf dem Bildschirm aus.

Wenn du nun wieder die Adresse "http://travelloblog/article" in deinem Browser aufrufst, solltest du die Ausgabe eines nummerierten Array mit zwei Elementen erhalten, in dem jeweils ein assoziatives Array mit den Spalten und Werten enthalten ist.

Der Zugriff auf die Datenbanktabelle "article" hat somit problemlos geklappt. Wer seine SQL Abfragen sowieso immer zu Fuß erstellt, ist eventuell schon jetzt zufrieden. Wenn du dir die Arbeit aber weiter erleichtern möchtest, solltest du am besten weiter lesen.

Zend_Db_Table

Um Zend_Db_Table verwenden zu können, müssen wir eine Klasse erstellen, welche von Zend_Db_Table abgeleitet wird. Dafür erstelle bitte im Verzeichnis "/travelloblog/application/models" eine Datei mit Namen "ArticleModel.php" und folgendem rudimentären Code:

PHP:
  1. <?php
  2. class ArticleModel extends Zend_Db_Table {}
  3. ?>

Dann ändere bitte wieder die "indexAction" Methode in unserem "ArticleController" wie folgt ab:

PHP:
  1. <?php
  2. class ArticleController extends Zend_Controller_Action
  3. {
  4.     public function indexAction()
  5.     {
  6.         require_once 'Zend/Db.php';
  7.        
  8.         $params = array ('host'     => '127.0.0.1',
  9.                          'username' => 'root',
  10.                          'password' => '',
  11.                          'dbname'   => 'travelloblog');
  12.        
  13.         $db = Zend_Db::factory('PDO_MYSQL', $params);       
  14.        
  15.         require_once 'Zend/Db/Table.php';
  16.         Zend_Db_Table::setDefaultAdapter($db);
  17.        
  18.         require_once '../application/models/ArticleModel.php';
  19.         $article = new ArticleModel();
  20.        
  21.         Zend::dump($article);
  22.     }
  23.  
  24.     [...]
  25. }
  26. ?>

Jetzt rufe bitte wieder die Adresse "http://travelloblog/article" in deinem Browser auf. Wir erhalten eine Fehlermeldung, in der unter anderem folgendes steht:

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42S02]:
Base table or view not found: 1146 Table 'travelloblog.article_model' doesn't exist'

Zend_Db versucht also automatisch vom Namen der Model Klasse auf den Namen der Datenbanktabelle zu schließen. Die Tabelle "article_model" konnte somit nicht gefunden werden. Dies ist ja auch logisch, schließlich heißt unsere Tabelle auch "article". Jetzt könntest du auf die Idee kommen, die Model Klasse einfach in "Article" statt "ArticleModel" um zu nennen. Dies wäre aber eher suboptimal, da solch sehr einfach benannten Klassen irgendwann mit anderen Klassen kollidieren könnten.

Das Problem lässt sich einfach lösen, da wir in der Klasse "ArticleModel" auch einen anderen Namen für die Tabelle angeben können. Öffne bitte wieder die Datei "ArticleModel.php" im Verzeichnis "/travelloblog/application/models" und erweitere die Klasse wie folgt:

PHP:
  1. <?php
  2. class ArticleModel extends Zend_Db_Table
  3. {
  4.     protected $_name = 'article';
  5. }
  6. ?>

Ein erneuter Aufruf von "http://travelloblog/article" zeigt jedoch wieder eine Fehlermeldung an, in der unter anderem folgendes steht:

Fatal error: Uncaught exception 'Zend_Db_Table_Exception' with message 'primary
key 'id' not in columns for table 'article''

In der Tabelle "article" konnte also kein Primärschlüssel "id" gefunden werden. Was bedeutet dies? Zend_Db_Table erwartet standardmäßig in einer Tabelle einen Primärschlüssel mit Namen "id". Da unser Primärschlüssel in der Tabelle "article" jedoch "art_id" heißt, erhalten wir diese Fehlermeldung.

Das Problem lässt sich jedoch auch recht einfach lösen, da wir in der Klasse "ArticleModel" auch einen eigenen Primärschlüssel angeben können. Ändere die Datei "ArticleModel.php" wie folgt:

PHP:
  1. <?php
  2. class ArticleModel extends Zend_Db_Table
  3. {
  4.     protected $_name = 'article';
  5.     protected $_primary = 'art_id';
  6. }
  7. ?>

Ein erneuter Aufruf von "http://travelloblog/article" in deinem Browser sollte die Fehlermeldung verschwinden lassen. Stattdessen wird ein Objekt vom Typ "ArticleModel" ausgegeben, was ganz nett aussieht, aber uns nicht viel weiter hilft. Wir möchten also gerne wieder die Inhalte dieser Tabelle ausgeben. Dafür ändere bitte erneut die "indexAction" Methode in unserem "ArticleController" wie folgt ab:

PHP:
  1. <?php
  2. class ArticleController extends Zend_Controller_Action
  3. {
  4.     public function indexAction()
  5.     {
  6.         require_once 'Zend/Db.php';
  7.        
  8.         $params = array ('host'     => '127.0.0.1',
  9.                          'username' => 'root',
  10.                          'password' => '',
  11.                          'dbname'   => 'travelloblog');
  12.        
  13.         $db = Zend_Db::factory('PDO_MYSQL', $params);       
  14.        
  15.         require_once 'Zend/Db/Table.php';
  16.         Zend_Db_Table::setDefaultAdapter($db);
  17.        
  18.         require_once '../application/models/ArticleModel.php';
  19.         $article = new ArticleModel();
  20.        
  21.         $rowset = $article->fetchAll();
  22.  
  23.         Zend::dump($rowset);
  24.     }
  25.  
  26.     [...]
  27. }
  28. ?>

Bei einem erneuten Aufruf der Adresse "http://travelloblog/article" in deinem Browser wird dir dann ein Objekt vom Typ "Zend_Db_Table_Rowset" ausgegeben. Dieses Objekt enthält unter anderem auch ein Array mit den Daten aus der Tabelle. Was du alles mit einem Zend_Db_Table_Rowset Objekt anfangen kannst, siehst du im nächsten Kapitel.

Zend_Db_Table_Rowset und Zend_Db_Table_Row

Wie schon weiter oben beschrieben handelt es sich bei Zend_Db_Table_Rowset um eine Sammlung von Zend_Db_Table_Row Objekten, die einfach durchlaufen werden können.

Um durch die Ergebnismenge zu iterieren und einzelne Zeilen ausgeben zu können, ändere bitte wieder die "indexAction" Methode im "ArticleController" ab.

PHP:
  1. <?php
  2. class ArticleController extends Zend_Controller_Action
  3. {
  4.     public function indexAction()
  5.     {
  6.         [...]
  7.  
  8.         $rowset = $article->fetchAll();
  9.        
  10.         echo '<h3>Rowset</h3>';
  11.         Zend::dump($rowset->toArray());
  12.        
  13.         foreach($rowset as $key => $row)
  14.         {
  15.             echo '<h3>Row ' . $key . '</h3>';
  16.             Zend::dump($row->toArray());
  17.            
  18.             echo '<h3>Row ' . $key . ' Title</h3>';
  19.             Zend::dump($row->artTitle);
  20.         }
  21.     }
  22.  
  23.     [...]
  24. }
  25. ?>

Wenn du nun erneut die Adresse "http://travelloblog/article" in deinem Browser aufrufst, siehst du mehrere durch Überschriften getrennte Ausgaben. Zuerst werden über $rowset->toArray() alle Ergebnisse in einem gesamten Array ausgegeben. Danach werden dann für jede Zeile mit Hilfe von $row->toArray() alle Spalten ausgegeben.

Neben dem Zugriff über die $row->toArray() Methode kann auch direkt auf einzelne Spalten zugegriffen werden. Hierbei musst du aber beachten, dass die Spaltennamen statt mit Unterstrichen in der so genannten CamelCase Schreibweise angegeben werden müssen. Aus "art_title" wird somit "artTitle".

Aufräumarbeiten

Bevor wir weitermachen, schaue dir bitte einmal den Code in ArticleController::indexAction genauer an. Es macht keinen großen Sinn, in einer Aktionsmethode, die eine Datenbank verwendet, die Parameter für den Zugriff auf die Datenbank abzulegen. Controller Klassen sollten derartige Konfigurationsparametern nicht enthalten.

Außerdem stören mich auch die viele Aufrufe von require_once(), die mehrmals in ArticleController::indexAction zu finden sind, und die Angabe des Verzeichnisses, in dem unsere Model Klassen liegen.

Kopiere bitte aus ArticleController::indexAction die Zeilen von "require_once 'Zend/Db.php';" bis einschließlich "require_once '../application/models/ArticleModel.php';". Öffne dann unsere Bootstrap Datei "index.php" im Verzeichnis "/travelloblog/public". Füge den kopierten Code hinter der Zeile "$dir = '../application/controllers';" wieder ein. Die kopierten Zeilen kannst du dann aus ArticleController::indexAction entfernen, so dass diese Aktionsmethode deutlich weniger Code enthält.

Die Bootstrap Datei sollte nun wie folgt aussehen:

PHP:
  1. <?php
  2. [...]
  3.  
  4. $dir = '../application/controllers';
  5.  
  6. Zend::loadClass('Zend_Db');
  7.  
  8. $params = array ('host'     => '127.0.0.1',
  9.                  'username' => 'root',
  10.                  'password' => '',
  11.                  'dbname'   => 'travelloblog');
  12.  
  13. $db = Zend_Db::factory('PDO_MYSQL', $params);
  14.  
  15. Zend::loadClass('Zend_Db_Table');
  16. Zend_Db_Table::setDefaultAdapter($db);
  17.  
  18. require_once '../application/models/ArticleModel.php';
  19.  
  20. $controller = Zend_Controller_Front::getInstance();
  21.  
  22. [...]
  23. ?>

Wenn du wieder die Adresse "http://travelloblog/article" aufrufst, sollten alle Einträge aus der Tabelle "article" weiterhin angezeigt werden. Das Ganze lässt sich auch noch weiter optimieren. Das Laden unserer Model Klasse können wir dadurch vereinfachen, dass wir das Verzeichnis mit unseren Model Klassen zum include_path hinzufügen.

Rufe bitte die Datei "set_include_path.php" im Verzeichnis "/travelloblog/application/config" auf und füge das Verzeichnis zu den Model Klassen hinzu:

PHP:
  1. <?php
  2. $include_path = get_include_path();
  3. $include_path.= PATH_SEPARATOR . 'e:\travelloblog\library\zf';
  4. $include_path.= PATH_SEPARATOR . 'e:\travelloblog\application\models'
  5.  
  6. set_include_path($include_path);
  7. ?>

In unsere Bootstrap Datei können wir das Laden der "ArticleModel.php" Datei dann vereinfachen. Statt des "require_once()" Aufrufs mit der Verzeichnisangabe, können wir jetzt auch die Zend::loadClass() Methode verwenden.

PHP:
  1. <?php
  2. [...]
  3.  
  4. Zend::loadClass('ArticleModel');
  5.  
  6. [...]
  7. ?>

Jetzt stören mich vorerst noch die vielen Aufrufe von Zend::loadClass(). Bisher haben wir in unserer Bootstrap Datei schon fünf Aufrufe von Zend::loadClass() und unser Projekt steht erst am Anfang. Um die Bootstrap Datei zu entschlacken hilft uns die Methode __autoload().

__autoload() nutzen

Die Verwendung von __autoload() ist recht simpel. Wenn du in PHP 5 eine Funktion __autoload() deklariert hast, wird diese automatisch aufgerufen, sobald du eine noch nicht definierte (geladene) Klasse verwendest. __autoload() bekommt beim Aufruf einen Parameter mit den Namen der Klasse übergeben.

In unserer Bootstrap Datei füge hinter der Zeile "require_once 'Zend.php';" bitte die Deklaration unserer __autoload() Funktion ein.

PHP:
  1. <?php
  2. [...]
  3.  
  4. require_once 'Zend.php';
  5.  
  6. function __autoload($class)
  7. {
  8.     Zend::loadClass($class);
  9. }
  10.  
  11. [...]
  12. ?>

Danach kannst du die fünf weiteren Aufrufe von Zend::loadClass() aus der Bootstrap Datei entfernen. Nach einem erneuten Aufrufe der Adresse "http://travelloblog/article" in deinem Browser sollte weiterhin alles funktionieren.

Die Bootstrap Datei ist zwar immer noch nicht optimal, aber dazu kommen wir später noch einmal zurück. Immerhin ist unsere Aktionsmethode nun deutlich übersichtlicher geworden.

Zeilen lesen

Da die Ausgabe von Ergebnismengen aus einer Datenbank per Zend_Db_Table_Rowset gut geklappt hat, möchten wir nun einmal das Lesen, Ändern, Erstellen und Löschen von einzelnen Zeilen aus der Datenbank testen. Wir belassen die "indexAction" Methode im "ArticleController" so wie sie momentan ist.

Für das Lesen einer Zeile öffne bitte stattdessen den "ArticleController" und ändere die "showAction" Methode wie folgt:

PHP:
  1. <?php
  2. class ArticleController extends Zend_Controller_Action
  3. {
  4.     [...]
  5.  
  6.     public function showAction()
  7.     {
  8.         $article = new ArticleModel();
  9.        
  10.         $row = $article->fetchRow('art_id = 1');
  11.        
  12.         Zend::dump($row->toArray());
  13.     }
  14.    
  15.     [...]
  16. }
  17. ?>

Über die Methode $article->fetchRow() kannst du direkt eine Zeile aus der Tabelle lesen. Als ersten Parameter kannst du eine WHERE Klausel und als zweiten eine ORDER BY Klausel angeben. Rufe einfach die Adresse "http://travelloblog/article/show" in deinem Browser auf, dann siehst du, dass das Lesen eines einzelnen Datensatzes aus unserer Artikeltabelle anhand des Primärschlüssels "art_id" also auch sehr einfach funktioniert.

Zeilen ändern

Kommen wir zum Ändern eines Datensatzes. Dafür gebe in der Methode "changeAction" bitte folgendes ein:

PHP:
  1. <?php
  2. class ArticleController extends Zend_Controller_Action
  3. {
  4.     [...]
  5.  
  6.     public function changeAction()
  7.     {
  8.         $article = new ArticleModel();
  9.        
  10.         $row = $article->fetchRow('art_id = 1');
  11.        
  12.         $newDate = date('Y-m-d H:i:s');
  13.        
  14.         $row->artUdate = $newDate;
  15.        
  16.         $row->save();
  17.        
  18.         Zend::dump($row->toArray());
  19.     }
  20.    
  21.     [...]
  22. }
  23. ?>

Zum Ändern der Werte eines Zend_Db_Table_Row Objektes musst du den Eigenschaften einfach nur die geänderten Werte zuweisen. Danach rufst du die Funktion $row->save() auf, um die Zeile in der Datenbank zu aktualisieren.

Rufe einfach die Adresse "http://travelloblog/article/change" in deinem Browser auf, um das Ergebnis zu sehen. Wenn du nicht glaubst, dass das Datum wirklich gespeichert wurde, rufe danach wieder "http://travelloblog/article/show" auf. Auch dort sollte dann ein aktueller Wert für die Spalte "art_udate" angezeigt werden.

Zeilen anlegen

Als nächsten schauen wir uns das Anlegen eines neuen Datensatzes an. Dafür gebe in der Methode "createAction" bitte folgendes ein:

PHP:
  1. <?php
  2. class ArticleController extends Zend_Controller_Action
  3. {
  4.     [...]
  5.  
  6.     public function createAction()
  7.     {
  8.         $article = new ArticleModel();
  9.        
  10.         $newDate = date('Y-m-d H:i:s');
  11.        
  12.         $data = array(
  13.             'art_user_id' => 1,
  14.             'art_cdate'   => $newDate,
  15.             'art_udate'   => $newDate,
  16.             'art_title'   => 'Our new entry',
  17.             'art_text'    => 'Here will be lots and lots of text.',
  18.             'art_teaser'  => 'New teaser'
  19.         );
  20.        
  21.         $id = $article->insert($data);
  22.        
  23.         $row = $article->fetchRow('art_id = ' . $id);
  24.        
  25.         Zend::dump($row->toArray());
  26.     }
  27.    
  28.     [...]
  29. }
  30. ?>

Zuerst wird ein Array mit allen Spalten (außer dem Primärschlüssel) erstellt und dann über die Methode $article->insert($data) in die Datenbank geschrieben. Von dieser Methode erhalten wir den Primärschlüssel des neuen Datensatzes zurück. Danach lesen wir den neuen Datensatz gleich wieder aus und zeigen ihn ein.

Bitte rufe die Adresse "http://travelloblog/article/create" auf, um den Datensatz anzulegen und auszugeben. Du solltest die Adresse aber nicht zu oft aufrufen, weil ansonsten jedes Mal ein neuer Datensatz angelegt wird. Diese könntest du dann aber auch wieder manuell aus deiner Datenbank löschen.

Zeilen löschen

Das ist auch das Stichwort für den letzten Teil diese Kapitels. Nun möchten wir einen Datensatz löschen. Dies geschieht in der Methode "deleteAction" von unserem "ArticleController":

PHP:
  1. <?php
  2. class ArticleController extends Zend_Controller_Action
  3. {
  4.     [...]
  5.  
  6.     public function deleteAction()
  7.     {
  8.         $article = new ArticleModel();
  9.        
  10.         $newDate = date('Y-m-d H:i:s');
  11.        
  12.         $data = array(
  13.             'art_user_id' => 1,
  14.             'art_cdate'   => $newDate,
  15.             'art_udate'   => $newDate,
  16.             'art_title'   => 'Our new entry',
  17.             'art_text'    => 'Here will be lots and lots of text.',
  18.             'art_teaser'  => 'New teaser'
  19.         );
  20.        
  21.         $id = $article->insert($data);
  22.        
  23.         $article->delete('art_id = ' . $id);
  24.        
  25.         echo 'Dataset ' . $id . ' was created and deleted straight afterwards';
  26.     }   
  27.  
  28.     [...]
  29. }
  30. ?>

Wir legen zuerst einen neuen Datensatz an und nutzen dann den zurückgegebenen Primärschlüssel, um den Datensatz gleich wieder zu löschen. Wenn du in deinem Browser die Adresse "http://travelloblog/article/delete" aufrufst, sollte der kurze Hinweistext ausgegeben werden.

Übung: die weiteren Model Klassen

Als kleine Übung bis zum nächsten Teil dieses Tutorials erweitere die Controller Klassen CategoryController und TagController um den Zugriff auf die jeweilige Model Klasse. Erstelle dafür als erstes die beiden Model Klassen und erweitere dann die vorhandenen Aktionsmethoden wie folgt:

  • indexAction: zeige alle Daten der Tabelle an
  • createAction: erstelle einen neuen Eintrag in der Tabelle
  • changeAction: ändere einen bestehenden Eintrag
  • deleteAction: erstelle einen neuen Eintrag in der Tabelle und lösche ihn gleich wieder.

Zur Kontrolle lade dir den aktuellen Stand des Tutorials runter. Dann kannst du deine Ergebnisse damit vergleichen.

Download

Der aktuelle Stand des Tutorials nach diesem vierten Teil kann herunter geladen werden. Hier sind auch alle Controller Klassen enthalten. Die Textdateien "empty.txt" in einigen Verzeichnissen habe ich nur angelegt, weil mein Winzip keine leeren Verzeichnisse im Zip Archiv anlegt:

Die Zip Datei enthält nicht die aktuelle Version des Zend Frameworks. Dies musst du bitte selber in das entsprechende Verzeichnis kopieren.

Zusammenfassung

In diesem vierten Teil des Zend Framework Tutorials haben wir die Model Komponente unseres TravelloBlogs mit Hilfe der Zend_Db Komponente des Zend Frameworks realisiert. Dabei haben wir die verschiedenen Teilkomponenten wie Zend_Db_Adapter und Zend_Db_Table kennen und nutzen gelernt.

Die Ausgabe der Daten ist zwar noch nicht zufriedenstellend, da wir uns bisher noch nicht mit der View Komponente des MVC Entwurfsmusters beschäftigt haben. Im nächsten Teil steht jedoch Zend_View auf dem Programm, so dass wir dann die ersten vollständig implementierten Abschnitte unseres TravelloBlogs realisieren können.

Fragen, Probleme und Anregungen bitte nicht per E-Mail senden, sondern hier in die Kommentare stellen. Dann haben alle etwas davon.

Change Log

An dieser Stelle werden Änderungen an diesem Tutorial Teil zusammengefasst, die nach dem Ersterscheinen (11.9.2006) notwendig waren, z.B. durch neuere Versionen des Zend Frameworks oder Änderungen am Konzept des Tutorials oder den Anforderungen an unser TravelloBlog.

  • 12.09.2006: Fehler in Abschnitt Zeilen ändern korrigiert; dort stand im Quellcode "showAction()" statt "changeAction" (danke Daniel)
  • 12.09.2006: Fehler in Abschnitt Aufräumarbeiten korrigiert; dort stand im 3. Quellcode "Zend::loadClass('Article');" statt "Zend::loadClass('ArticleModel');" (danke Daniel)
  • 12.09.2006: Fehler in Abschnitt Zend_Db korrigiert; dort stand im 3. und 4. Quellcode jeweils "class Article" statt "class ArticleModel" (danke Aaron)
  • 25.09.2006: Fehler in Abschnitt Aufräumarbeiten korrigiert; dort wurde von "Zend::loadClass('Zend_Db')" gesprochen statt von "require_once 'Zend/Db.php'" (danke Tobias)
  • 08.10.2006: Erstellen eines neuen Datums vereinfacht (danke Peter)
  • 05.11.2006: Tutorial an Release 0.2.0 angepasst
  • 28.12.2006: für Release 0.6.0 aktualisiert

Navigation

53 Antworten für “Zend Framework Tutorial Teil 4: MVC Design Pattern und Zend_Db”

  1. Ralfs PHP Blog » Zend Framework Tutorial Teil 1: Einführung und Anforderungen sagt:

    [...] MVC Design Pattern und Zend_Db [...]

  2. Ralfs PHP Blog » Zend Framework Tutorial Teil 3: MVC Design Pattern und Zend_Controller sagt:

    [...] Zend Controller, Zend Controller RewriteRouter, ZF Tutorial Bookmark: del.icio.us yigg.de mister-wong.de  [...]

  3. Christian sagt:

    Hi Ralf,

    wollte mich erstmal für Deine Tipps bedanken und ein Lob für Dein klasse Tutorial aussprechen.

    Nachdem ich mich jetzt brav in die Zend_Controller klassen und funktionen eingearbeitet habe programmiere ich mir mein Modulbasiertes Framework. Vielleicht hast Du ja kurz Zeit und kannst mir Deine Meinung dazu schreiben:

    Ich habe die Zend_Controller_Front mit einer eigenen Klasse erweitert um die eigentliche library nicht ändern zu müssen. (sowie Zend_Controller_Router und Zend_Controller_Dispatcher in meine lib kopiert)

    Im Zend_Controller_Router wo die URL zerlegt wird habe ich nun eine Datenbankabfrage drin und hole mir anhand des controllernamen alle controller die ich für diese Seite laden möchte (also meine Module) erstelle daraus Zend_Controller_Dispatcher_Token und gebe diese als array an Mein_Controller_Front zurück. Jetzt wird jedes actionObject aus dem Array mit den Standardfunkionen aufgerufen. Das einzige was ich hier noch geändert habe ist ein outputbuffering um den Inhalt der "Module" einzeln zu erhalten. Das alles wieder in ein Array gepackt und zurückgegeben.

    Jetzt habe ich jedes Modul in einer MVC Struktur und kann diese beliebig platzieren.

    Totaler quatsch oder ein verfolgbarer Ansatz ?!

    Gruß
    Christian

  4. Daniel Henninger sagt:

    Hallo Ralf,

    habe schon sehnsüchtig auf den nächsten Teil des Tutorials gewartet. Vielen Dank für Deine Mühe.

    Eben habe ich den indexController geändert, und bekomme beim Aufruf von http://travelloblog/article folgende Fehlermeldung: Fatal error: Class 'Zend_Db' not found in X:\xampp\htdocs\travelloblog\application\controllers\ArticleController.php on line 11

    Ist bei Deinem Bespiel Zeile 13. #
    $db = Zend_Db::factory('PDO_MYSQL', $params);

    Datenbank habe ich aber angelegt, und den Benutzer root alle Rechte erteilt.
    Woran könnte das liegen?

    Gruß,
    Daniel

  5. Daniel Henninger sagt:

    Hat sich gerade geklärt. Da war etwas mit den Pfaden noch nicht ok.
    Danke.

  6. Aaron Müller sagt:

    Hallo Ralph!
    Erstmal genial das du diese Tutorial-Reihe machst, und ich hoffe das bald noch weitere Kapitel dazukommen. Echt Super!

    Dann habe ich glaube ich ein paar Tippfehler gefunden:

    Quellcode 5 und 6:
    #

  7. Aaron Müller sagt:

    Irgend wie wurde mein Kommentar gekürzt. Vermutlich weil PHP-Code mit dabei war. Gibt es einen speziellen Tag in deinem Blog, mit dem ich PHP-Code markieren kann?

  8. Daniel Henninger sagt:

    Kleiner Fehlerteufel...

    - anstatt "Zend::loadClass('Article');" bitte "Zend::loadClass('ArticleModel');" für require_once verwenden.

    - Im Abschnitt Zeile ändern "public function changeAction()" anstatt "public function showAction()" verwenden.

    Macht aber nichts, wenn man die Fehler findet, fängt man an es zu verstehen ;-))

  9. Ralf Eggert sagt:

    @Christian,

    es ist auf jeden Fall der richtige Ansatz, die Zend Framework Klassen zu erweitern. Du kannst sie dann sogar in einem ähnlichen Verzeichnisschema ablegen wie die eigentlichen Zend Klassen. Wenn du also Mein_Controller_Front hast, kannst du das als Mein/Controller/Front.php parallel zum Zend/Controller/Front.php ablegen und dann auch per Zend::loadClass() laden. Wir kommen im Laufe des Tutorials auch noch dazu, die bestehenden Framework Klassen zu erweitern.

    Die Module in einer Datenbank zu verwalten, ist ein interessanter Ansatz und macht durchaus Sinn je nach dem, was deine Anwendung leisten soll. Tiefer durchdacht habe ich das aber noch nicht.

    Gruß,

    Ralf

  10. Ralf Eggert sagt:

    Hallo Aaron,

    also in den Blog Beiträgen kann ich

    PHP:
    1. echo 'Hallo Welt!';

    verwenden, was ich in diesem Kommentar mal getestet habe. Ansonsten musst du die spitzen Klammern maskieren oder einfach weg lassen.

    Kannst du bitte noch mal schreiben, wo sich die Fehler eingeschlichen haben?

    Gruß,

    Ralf

  11. Ralf Eggert sagt:

    @Aaron,

    Oh, das funktioniert hier auch in den Kommentaren, also verwende die Markierungen [ php ] und [ / php ] aber ohne die Leerzeichen.

    Gruß,

    Ralf

  12. Ralf Eggert sagt:

    @Daniel, danke für die Fehlerreports. Habe die Fehler jetzt korrigiert.

    @Aaron, habe nun auch entdeckt, was du wohl meintest.

    Ich hoffe, dass das nun alle Fehler waren :-)

    Gruß,

    Ralf

  13. Ralfs PHP Blog » Zend Framework Tutorial Teil 5: MVC Design Pattern und Zend_View sagt:

    [...] Im vierten Teil vom Zend Framework Tutorial haben wir die Zend_Db Komponente und deren Teilkomponenten kennen gelernt, um auf einen Datenbank zugreifen zu können. Die Ausgabe haben wir aber nur unformatiert auf dem Bildschirm ausgegeben, da wir bisher noch keine Templates eingesetzt hatten. Wenn du die ersten vier Teile noch nicht gelesen hast, hole dies bitte schnell nach. [...]

  14. Torsten sagt:

    Hi Ralf,

    nach dem Abarbeiten der Datenbankanbindung mittels Zend_Db_Table erhalte ich folgende Fehlermeldung:

    http://travelloblog/article

    Fatal error: Uncaught exception Zend_Db_Adapter_Execption with message The PDO extension is required for this adapter but not loaded in [...]\Pdo\Abstract.php:75 Stack trace: #0
    [...]

    Gruß
    Torsten

  15. Torsten sagt:

    dachte mir Zend::loadClass('Zend_Db_Table'); und Zend::loadClass('Zend_Db'): einzufügen. Zend_Db_Table wird nicht gefunden. Weiß nicht weiter.

    Torsten

  16. Ralf Eggert sagt:

    Hallo Torsten,

    du musst noch die PDO Extension laden. Öffne mal deine php.ini Datei und suche nach der Stelle

    extension=php_pdo.dll
    extension=php_pdo_mysql.dll

    Vor beiden Zeilen musst du das ; entfernen. Klappt es dann?

    Gruß,

    Ralf

  17. Torsten sagt:

    Hallo Ralf,

    jetzt hab ich folgende Fehlermeldung:

    Fatal error: Call to undefined method PDO::getavailabledrivers() in [...]

    Verwende XAMPP mit PHP5. Habe die php.ini im Verzeichnis c:\xampp\apache\bin editiert. Denke mal das war die richtige von 5000 php.ini's unter xampp :)

    Gruß
    Torsten

  18. Torsten sagt:

    ich bin doch ein Drottel :)
    hatte ne ältere PHP Version am laufen...

    Torsten

  19. Ralf Eggert sagt:

    Hallo Torsten,

    danke, dass du dich nochmal gemeldet hast, dass das Problem nun gelöst ist. Eigentlich wollte ich in meiner Mittagspause gleich mal bei dem Rechner nachschauen, wo ich testweise Xampp laufen habe. Schön, dass das Problem nun gelöst ist.

    Gruß,

    Ralf

  20. Felix Pfeiffer sagt:

    Hallo,
    wie schon zu "Kapitel3" habe ich auch hier wieder eine Frage.
    Nachdem ich die ArticleController.php und index.php "gereinigt" habe kommt er mir mit einer komischen Fehlermeldung:
    Fatal error: Class 'ArticleModel' not found in G:\xampp\htdocs\travelloblog\application\controllers\ArticleController.php on line 34
    Ich habe jetzt die ArticleController.php aus dem zip-Archiv genommen. In Zeile 34 ist folgendes im Quellcode:
    }

    Benötigt eine geschweifte Klammer seit neustem eine eigene Klasse?? :-)
    Wie gesagt, da finde ich den Fehler einfach nicht.

    Ich verwende übrigens auch den XAMPP unter Windows XP.

    Danke für einen kleinen Tipp.

    Felix

  21. Felix Pfeiffer sagt:

    Sorry, die Sache hat sich erledigt.
    Man muss wirklich jede kleine Änderung im Kopf oder auf einem Zettel behalten ;-)

  22. Ralf Eggert sagt:

    Hallo Felix,

    ok, dann bin ich aber froh, dass sich das Problem erledigt hat. Dafür sind übrigens auch die Zip-Archive gedacht. Auch wenn sich dort ebenfalls mal ein Fehler einschleichen kann... ;-(

    Gruß,

    Ralf

  23. Tobias sagt:

    Der Fehlerteufel gibt leider nicht auf. In Deinem Abschnitt über die Aufräumarbeiten hat sich eine Unstimmigkeit eingeschlichen. Du schreibst hier: "Außerdem stören mich auch die viele Aufrufe von Zend::loadClass()". Leider hast Du in den Quellcodes 1,2,3 und 6 garnicht diese Aufrufe genommen, sondern nutzt nur die "require_once 'Zend/Db.php';" Aufrufe.
    Dies sollte man ändern oder als Miniquizz im Tutorial lassen, da die Lösung wie man nun seine Dateien aufräumen kann steht ja nun hier ;)

  24. Ralf Eggert sagt:

    Danke Tobias für den Hinweis. Habe das gleich korrigiert und in das Changelog mit aufgenommen. :-)

    Gruß,

    Ralf

  25. Ralfs PHP Blog » Zend Framework Tutorial Teil 7: MVC Design Pattern für weitere Controller sagt:

    [...] Die neue Kategorienliste macht natürlich erst so richtig Spaß, wenn wir Artikel auch beliebig viele Kategorien zuordnen können. Wie du dich vielleicht erinnerst, haben wir in Teil 4 dieses Tutorials sogar eigens dafür die Tabelle "art2cat" angelegt. Wir haben aber für diese - ich nenne sie mal Verknüpfungstabelle – keine von Zend_DB abgeleitete Model Klassen im Verzeichnis "/application/models" angelegt. [...]

  26. Volker Zidek sagt:

    Hallo Ralph und die anderen,
    erst mal vielen Dank für das reichhaltige, sinnvolle und wirklich gute tutorial.

    Ich habe irgendwie das gleiche Problem wir Thorsten mit der PDO-extension.
    Ich habe php5.1.6 mit den erweiterungen der zendplatform am laufen.
    bei mir standen trotzdem keine pdo-extensions defaulmäsig drin.
    ich habe dann deine beiden Einträge:

    extension=php_pdo.dll
    extension=php_pdo_mysql.dll

    in die php.ini geschrieben, welche mir in phpinfo.php als geladen genannt wurde.

    Mindestens diese beiden dll's sind auch in meinem php/ext ordner vorhanden.
    Allerdings stand in der php.ini als extension_dir "./"
    Welchen ich dannn mit extension_dir = "./;C:\php\ext" erweitert habe um sicher
    zu gehen dass er sie auch findet.

    Dennoch bekomme ich bei http://travelloblog/Article :
    Fatal error: Uncaught exception 'Zend_Db_Adapter_Exception' with message 'The PDO extension is required for this adapter but not loaded' in ...

    Wie könnte ich sonst testen ob meine PDO extension korrekt geladen ist ?
    Was könnte es sonst noch sein ?

    Viele Grüsse
    Volker

  27. Ralf Eggert sagt:

    Hallo Volker,

    also bei mir stand als extension_dir auch erst das hier:

    extension_dir = "./"

    was ich dann wie folgt geändert habe:

    extension_dir = "c:\wamp\php5\ext"

    Ich habe also das ./ entfernt. Hast du es so mal probiert?

    Gruß,

    Ralf

  28. Wolfgang sagt:

    Hallo Zusammen :)

    Ich hab mal eine Frage zur Zend_Db Komponente.
    Ich hab zwei Tabellen xmlfile (xmlfile_id als PK) und content(content_id als PK und xmlfile_id als FK)
    Wie kann ich die beiden jetzt mit der Zend Komponente joinen ?

    CODE:
    1. $xml = new XmlModel();
    2. $rowset = $xml-&gt;fetchAll('select * from xmlfile left join content using(xmlfile_id)');
    3. Zend::dump($rowset-&gt;toArray());

    Dieser Versuch bringt leider eine Fehlermeldung (was eigentlich auch klar ist, aber ich weiß nicht wie ich es sonst machen soll):
    [quote]
    Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064
    [/quote]

    Danke.

  29. Ralf Eggert sagt:

    Hallo Wolfgang,

    an dem Thema wird gerade gearbeitet. Hier findest du auch ein Beispiel für die Umsetzung.

    http://framework.zend.com/issues/browse/ZF-34

    Gruß,

    Ralf

  30. Wolfgang sagt:

    Danke für die Antwort. Werd ichs wohl anders machen, die Lösungen sind mir alle ein bisschen zu dirty...;)

    Gruß,
    Wolfgang

  31. thomas sagt:

    Ersteinmal vielen dank für dieses tolle Tutorial.

    Ich habe allerdings eine kleines problem mit meiner MAC (apple) xampp installition. es fehlen mir so ziemlich alle dynamic extions unter anderem auch die

    extension=php_pdo.dll
    extension=php_pdo_mysql.dll

    ich denke mal aufgrund dieser fehlenden extension bekomme auch die nun folgende Fehlermeldung.

    Uncaught exception 'Zend_Db_Adapter_Exception' with message 'The mysql driver is not currently installed'

    ich benutze die letzte aktuelle version von xampp macosx 06a.

    wo bekomme ich am besten die extensions her ?

    grüße thomas

  32. Bleistift sagt:

    Ich hab auch einen Mac... Aber XAMP nutze ich nicht (mehr). Ich empfehle: http://www.mamp.info :)

  33. thomas sagt:

    Das problem was ich mit mamp habe ist, das es in letzter zeit nicht mehr geupdated wird. ich hatte es davor auch auf meinem mac laufen. nun ja dann werde ich wohl wieder zurück switchen.

  34. thomas sagt:

    ich habe jetzt mal wieder meinen mamp server ausgebuddelt und habe auch bis zur datenbank implementation alles hinbekommen. der datenbank server benutzt in mamp den port 8889 d.h. -> host = localhost:8889

    ich bekomme nun mit mamp die folgende Fehlermeldung wenn ich den article controller ausführe.

    Fatal error: Uncaught exception 'Zend_Db_Adapter_Exception' with message 'SQLSTATE[HY000] [2005] Unknown MySQL server host 'localhost:8889' (1)'. auf phpmyadmin habe ich zugriff deshalb läuft die db auch.

    falls mir jemand helfen kann, würde ich mich sehr über eine Antwort freuen.

    Gruß thomas

  35. thomas sagt:

    sorry für das spamming :( ich hab den arraywert für host von localhost:8889 auf localhost gewechselt und schon functionierte es ! :) sorry nochmal. aber vieleicht hilf es ja mal den mamp usern.

  36. Benjamin Klaile sagt:

    Hallo,
    aus der TODO.txt im Verzeichnis Zend/Db/Adapter

    ----
    Oracle Support (ext/oci8)

    - Currently broken
    - Adapter needs to be refactored to use Zend_Db_Adapter_Abstract
    - Some work left to be done (see @todo)

    MySQL Support (ext/mysqli)

    - Currently broken
    - Adapter needs to be refactored to use Zend_Db_Adapter_Abstract
    - Very large amount of work left to be done (see @todo)

    Zend_Db_Adapter_Abstract

    - Currently should work
    - John Coggeshall will improve transaction support
    ----

    Vielleicht als Ergänzung zu diesem Kapitel. Ich hab mich nämlich gerade gewundert, warum ich folgende Meldung erhalten habe:
    ---
    Uncaught exception 'Zend_Exception' with message 'File "Zend\Db\Adapter\Mysqli.php" was not found.'
    ---

    Jau, nur falls jemand das gleiche "Problem" haben sollte.

    Grüße, Ben.

  37. Bleistift sagt:

    Kann man die "unschönen" und für den Produktiveinsatz nicht geeigneten Fehlermeldungen (Beispiel: Syntaxfehler im MySQL-Query) des Zend Frameworks eigentlich irgendwie abfangen um sie zu loggen (ähnlich wie set_error_handler())?

  38. Michael Maier sagt:

    Im [URL="http://www.ralfeggert.de/2006/09/11/zend-framework-tutorial-mvc-design-pattern-zend_db/#zend_db_table"]Teil 4 Zend_Db_Table[/URL] steht, dass man eine Fehlermeldung erhält, da der Tabellenname nicht gefunden wird, jedoch "schluckt" folgender Teil in der bootstrap Datei alle Exceptions:

    PHP:
    1. try
    2. {
    3.     $controller-&gt;dispatch();
    4. }
    5. catch (Exception $e)
    6. {
    7.     require_once($dir . '/IndexController.php');
    8.     IndexController::norouteAction();
    9. }

    Ich habe das ein bisschen geändert:

    PHP:
    1. try
    2. {
    3.     $controller-&gt;dispatch();
    4. }
    5. catch (Zend_Controller_Dispatcher_Exception $e)
    6. {
    7.     require_once($dir . '/IndexController.php');
    8.     IndexController::norouteAction();
    9. }catch(Exception $e)
    10. {
    11.     Zend::dump($e);
    12.     //dann eventuell loggen der Exception und weiterleiten auf eine Fehlerseite
    13. }

  39. Ralf Eggert sagt:

    Hallo Michael,

    danke für den Hinweis. Dieser globale Catch für alle Exceptions ist sowieso nur ein ziemlich schlechter Workaround. Später stelle ich noch eine bessere Lösung vor...

    Gruß,

    Ralf

  40. Warui sagt:

    Nochmal wegen MAMP und MySQL
    bei mir hatte er auch Probleme und (der MySQL-Server) wollte auf 'localhost' nicht ansprechen.
    Wenn man jedoch folgende Werte benutzt, funktioniert es (auch mit dem Port):

    CODE:
    1. // benutze die standardeinstellungen von MAMP
    2. $params = array(
    3. 'host' =&gt; '127.0.0.1',
    4. 'port' =&gt; '8889',
    5. 'username' =&gt; 'root',
    6. 'password' =&gt; 'root',
    7. 'dbname' =&gt; 'travelloblog'
    8. );
    9. $db = Zend_Db::factory('PDO_MYSQL',$params);

  41. Michi sagt:

    Hallo

    Erstmal ein Kompliment für dieses super Tutorial, ist wirklich hilfreich.

    Ich versuche mit Hilfe dieses Tutorials ein kleines Gästebuch zu bauen. Nun habe ich beim Verbinden auf die MySQL Datenbank ein Probelm. Und zwar heisst es, dass der PDO Treiber nicht geladen sei. Ich habe in der php.ini die folgenden Zeilen auskommentiert.

    extension=php_pdo.dll
    extension=php_pdo_mysql.dll

    Trotzdem erscheint folgende Fehlermeldung:

    Fatal error: Uncaught exception 'Zend_Db_Adapter_Exception' with message 'The mysql driver is not currently installed' in C:\wamp\www\guestbook\library\zf\Zend\Db\Adapter\Pdo\Abstract.php:88 Stack trace: #0 ......

    Kann mir eventuell jemand sagen, was ich vergessen hab?

    Besen Dank im Voraus!
    Michi

  42. Michi sagt:

    Hallo

    Ich bins nochmal. Ich hatte die falsche php.ini in meiner wamp instalation editiert und zwar jene im PHP verzeichnis anstatt der im Apache/bin verzeichnis. Nun scheint der Treiber geladen und die Abfraen auf die Datenbank funktionieren.

    Ich hoffe niemandem unnötig Arbeit gemacht zu haben!

    Trotzdem esten Dank!

    Michi

  43. Andreas sagt:

    Für alle Ubuntu (6.06 LTS) Users die Installation und Aktivierung von PDO

    sudo bash
    apt-get install php5-dev
    apt-get install php-pear
    apt-get install libmysqlclient15-dev

    pecl install pdo
    echo "extension=pdo.so" >> /etc/php5/apache2/php.ini
    /etc/init.d/apache2 restart
    PHP_PDO_SHARED=1 pecl install PDO_MYSQL
    echo "extension=pdo_mysql.so" >> /etc/php5/apache2/php.ini
    /etc/init.d/apache2 restart
    exit

  44. Dieter sagt:

    Aus irgend einem Grund mußte ich beim "Nachspielen" im Part "Aufräumarbeiten" das If-command "if (!class_exists('Zend'))" vor dem "require_once 'Zend.php';" noch rausschmeißen. Anderfalls bekam ich folgende Ausname

    Fatal error: Class 'Zend' not found in E:\phphome\public\index.php on line 10

    Kann mir jemand sagen warum genau das so ist; offensichtlich wurde das require_once 'Zend.php' nicht aufgerufen. Laut Handbuch prüft class_exists() ob die Klasse defiert ist - die Klasse sollte doch dannauch bereits geladen sein oder ????

  45. Thorsten sagt:

    Was mache ich wenn ich eine Datenbanktabelle habe mit einem Primärschlüssel der aus zwei Feldern besteht? D.h. es gibt nicht EIN Feld das eindeutig ist sondern ZWEI Felder.

    Im Manual und der API Dokumentation hab ich nichts darüber gefunden.

    Weiß das jemand?

  46. Marcus sagt:

    hallo,
    nachdem ich alles bereinigt habe, kommt immer folgender Fehler:
    "Fatal error: Class 'Zend_Controller_RewriteRouter' not found in ..."
    Woran kann das liegen?

    Bei mir läuft XAMPP. Ich hab auch schon mit deiner Bootstrap-Datei verglichen und keine Unstimmigkeiten feststellen können.

    Gruß
    Marcus

  47. Alex sagt:

    Für die unter euch dir versuchen unter ubuntu den pdo_mysql zu verwenden rate ich:

    http://paradigma.pt/ja/slog/index.php/2006/10/pdo_mysql_ubuntu_error_fixed.html

  48. Alex sagt:

    ach ja mysql > 5 vorrausgesetzt ;)

  49. Alex sagt:

    ups... sorry hätte selber mal die kommentare lesen sollen...

  50. Ole sagt:

    Hmm, gibt es eine möglichkeit ohne die pdo_mysql-Erweiterung in der php.ini auf die DB zuzugreifen? Teste das Tut gerade auf nem Webspace, nur ist dort leider die pdo nicht aktiv :(

  51. Maik sagt:

    Anmerkungen zu 1.0.0

    Anscheinend werden beim ArticleModel die Spalten nicht mehr im CamelCase dargestellt. Statt dessen wird mit dem eigentlichen Spaltennamen gearbeitet.

  52. Mark sagt:

    Anmerkungen zu 1.0.0

    Um Klassen automatisch zu laden, genügt nun der Aufruf von:

    Zend_Loader::registerAutoload();

  53. Ben sagt:

    Ahjo,
    Statt Zend::dump() wird nun Zend_Debug::dump() benutzt.

Hinterlasse eine Antwort