quickstart-create-model.xml 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!-- EN-Revision: 20482 -->
  3. <!-- Reviewed: no -->
  4. <sect1 id="learning.quickstart.create-model">
  5. <title>Ein Modell und eine Datenbank Tabelle erstellen</title>
  6. <para>
  7. Bevor wir anfangen nehmen wie etwas an: Wo werden diese Klassen leben, und wie werden wir
  8. Sie finden? Das Standardprojekt welches wir erstellt haben instanziert einen Autoloader. Wir
  9. können Ihm andere Autoloader anhängen damit er weiss wo andere Klassen zu finden sind.
  10. Typischerweise wollen wir das unsere verschiedenen MVC Klassen im selben Baum gruppiert sind
  11. -- in diesem Fall <filename>application/</filename> -- und meistens einen gemeinsamen Präfix
  12. verwenden.
  13. </para>
  14. <para>
  15. <classname>Zend_Controller_Front</classname> hat den Begriff von "Modulen", welche
  16. individuelle Mini-Anwendungen sind. Module mimen die Verzeichnisstruktur welche das
  17. <command>zf</command> Tool unter <filename>application/</filename> einrichtet, und von allen
  18. Klassen in Ihm wird angenommen das Sie mit einen gemeinsamen Präfix beginnen, dem Namen des
  19. Moduls. <filename>application/</filename> selbst ist ein Modul -- das "default" oder
  20. "application" Modul. Als solches richten wir das Autoloading für Ressourcen in diesem
  21. Verzeichnis ein.
  22. </para>
  23. <para>
  24. <classname>Zend_Application_Module_Autoloader</classname> bietet die Funktionalität welche
  25. benötigt wird um die verschiedenen Ressourcen unter einem Modul mit den richtigen
  26. Verzeichnissen zu verbinden, und auch einen standardmäßigen Namensmechanismus. Standardmäßig
  27. wird eine Instanz der Klasse wärend der Initialisierung des Bootstrap Objekts erstellt;
  28. unser Application Bootstrap verwendet standardmäßig das Modulpräfix "Application". Daher
  29. beginnen alle unsere Modelle, Formulare, und Tabellenklassen mit dem Klassenpräfix
  30. "Application_".
  31. </para>
  32. <para>
  33. Nehmen wir jetzt also an was ein Guestbook ausmacht. Typischerweise sind Sie einfach eine
  34. Liste ein Einträgen mit einem <emphasis>Kommentar</emphasis> (comment), einem
  35. <emphasis>Zeitpunkt</emphasis> (timestamp) und oft einer <emphasis>Email Adresse</emphasis>.
  36. Angenommen wir speichern diese in einer Datenbank, dann wollen wir auch einen
  37. <emphasis>eindeutigen Identifikator</emphasis> für jeden Eintrag. Wir wollen in der Lage
  38. sein einen Eintrag zu speichern, individuelle Einträge zu holen, und alle Einträge zu
  39. empfangen. Als solches könnte das Modell einer einfachen Guestbook API wie folgt aussehen:
  40. </para>
  41. <programlisting language="php"><![CDATA[
  42. // application/models/Guestbook.php
  43. class Application_Model_Guestbook
  44. {
  45. protected $_comment;
  46. protected $_created;
  47. protected $_email;
  48. protected $_id;
  49. public function __set($name, $value);
  50. public function __get($name);
  51. public function setComment($text);
  52. public function getComment();
  53. public function setEmail($email);
  54. public function getEmail();
  55. public function setCreated($ts);
  56. public function getCreated();
  57. public function setId($id);
  58. public function getId();
  59. public function save();
  60. public function find($id);
  61. public function fetchAll();
  62. }
  63. ]]></programlisting>
  64. <para>
  65. <methodname>__get()</methodname> und <methodname>__set()</methodname> bieten uns bequeme
  66. Mechanismen an um auf individuelle Eigenschaften von Einträgen zuzugreifen und auf andere
  67. Getter und Setter zu verweisen. Sie stellen auch sicher das nur Eigenschaften im Objekt
  68. vorhanden sind die wir freigegeben haben.
  69. </para>
  70. <para>
  71. <methodname>find()</methodname> und <methodname>fetchAll()</methodname> bieten die Fähigkeit
  72. einen einzelnen Eintrag oder alle Einträge zu holen.
  73. </para>
  74. <para>
  75. Von hier an können wir über die Einrichtung unserer Datenbank nachdenken.
  76. </para>
  77. <para>
  78. Zuerst muss unsere <classname>Db</classname> Ressource initialisiert werden. Wie bei der
  79. <classname>Layout</classname> und <classname>View</classname> kann die Konfiguration für die
  80. <classname>Db</classname> Ressource angegeben werden. In der Datei
  81. <filename>application/configs/application.ini</filename> müssen die folgenden Zeilen in den
  82. richtigen Sektionen hinzugefügt werden.
  83. </para>
  84. <programlisting language="ini"><![CDATA[
  85. ; application/configs/application.ini
  86. ; Diese Zeile sind in den richtigen Sektionen hinzuzufügen:
  87. [production]
  88. resources.db.adapter = "PDO_SQLITE"
  89. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook.db"
  90. [testing : production]
  91. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-testing.db"
  92. [development : production]
  93. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-dev.db"
  94. ]]></programlisting>
  95. <para>
  96. Die endgültige Konfigurationsdatei sollte wie folgt aussehen:
  97. </para>
  98. <programlisting language="ini"><![CDATA[
  99. ; application/configs/application.ini
  100. [production]
  101. phpSettings.display_startup_errors = 0
  102. phpSettings.display_errors = 0
  103. bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
  104. bootstrap.class = "Bootstrap"
  105. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  106. resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
  107. resources.view[] =
  108. resources.db.adapter = "PDO_SQLITE"
  109. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook.db"
  110. [staging : production]
  111. [testing : production]
  112. phpSettings.display_startup_errors = 1
  113. phpSettings.display_errors = 1
  114. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-testing.db"
  115. [development : production]
  116. phpSettings.display_startup_errors = 1
  117. phpSettings.display_errors = 1
  118. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-dev.db"
  119. ]]></programlisting>
  120. <para>
  121. Es ist zu beachten das die Datenbank(en) unter <filename>data/db/</filename> gespeichert
  122. wird. Diese Verzeichnisse sind zu erstellen und weltweit-schreibbar zu machen. Auf
  123. Unix-artigen Systemen kann man das wie folgt durchführen:
  124. </para>
  125. <programlisting language="shell"><![CDATA[
  126. % mkdir -p data/db; chmod -R a+rwX data
  127. ]]></programlisting>
  128. <para>
  129. Unter Windows muss man die Verzeichnisse im Explorer erstellen und die Zugriffsrechte so zu
  130. setzen das jeder in das Verzeichnis schreiben darf.
  131. </para>
  132. <para>
  133. Ab diesem Punkt haben wir eine Verbindung zu einer Datenbank; in unserem Fall ist es eine
  134. verbindung zu einer Sqlite Datenbank die in unserem <filename>application/data/</filename>
  135. Verzeichnis ist. Designen wir also eine einfache Tabelle die unsere Guestbook Einträge
  136. enthalten wird.
  137. </para>
  138. <programlisting language="sql"><![CDATA[
  139. -- scripts/schema.sqlite.sql
  140. --
  141. -- Man muss das Datenbank Schema mit diesem SQL laden.
  142. CREATE TABLE guestbook (
  143. id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
  144. email VARCHAR(32) NOT NULL DEFAULT 'noemail@test.com',
  145. comment TEXT NULL,
  146. created DATETIME NOT NULL
  147. );
  148. CREATE INDEX "id" ON "guestbook" ("id");
  149. ]]></programlisting>
  150. <para>
  151. Und damit wir gleich einige Arbeitsdaten haben, erstellen wir ein paar Zeilen an Information
  152. um unsere Anwendung interessant zu machen.
  153. </para>
  154. <programlisting language="sql"><![CDATA[
  155. -- scripts/data.sqlite.sql
  156. --
  157. -- Man kann damit beginnen die Datenbank zu befüllen indem die folgenden SQL
  158. -- Anweisungen ausgeführt werden.
  159. INSERT INTO guestbook (email, comment, created) VALUES
  160. ('ralph.schindler@zend.com',
  161. 'Hallo! Hoffentlich geniesst Ihr dieses Beispiel einer ZF Anwendung!
  162. DATETIME('NOW'));
  163. INSERT INTO guestbook (email, comment, created) VALUES
  164. ('foo@bar.com',
  165. 'Baz baz baz, baz baz Baz baz baz - baz baz baz.',
  166. DATETIME('NOW'));
  167. ]]></programlisting>
  168. <para>
  169. Jetzt haben wir sowohl das Schema als auch einige Daten definiert. Schreiben wir also ein
  170. Skript das wir jetzt ausführen können um diese Datenbank zu erstellen. Natürlich wird das
  171. nicht in der Produktion benötigt, aber dieses Skriupt hilft Entwicklern die Notwendigkeiten
  172. der Datenbank lokal zu erstellen damit Sie eine voll funktionsfähige Anwendung haben. Das
  173. Skript ist als <filename>scripts/load.sqlite.php</filename> mit dem folgenden Inhalt zu
  174. erstellen:
  175. </para>
  176. <programlisting language="php"><![CDATA[
  177. // scripts/load.sqlite.php
  178. /**
  179. * Skript für das erstellen und Laden der Datenbank
  180. */
  181. // Initialisiert den Pfad und das Autoloading der Anwendung
  182. defined('APPLICATION_PATH')
  183. || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
  184. set_include_path(implode(PATH_SEPARATOR, array(
  185. APPLICATION_PATH . '/../library',
  186. get_include_path(),
  187. )));
  188. require_once 'Zend/Loader/Autoloader.php';
  189. Zend_Loader_Autoloader::getInstance();
  190. // Definiert einige CLI Optionen
  191. $getopt = new Zend_Console_Getopt(array(
  192. 'withdata|w' => 'Datenbank mit einigen Daten laden',
  193. 'env|e-s' => "Anwendungsumgebung für welche die Datenbank "
  194. . "erstellt wird (Standard ist Development)",
  195. 'help|h' => 'Hilfe -- Verwendung',
  196. ));
  197. try {
  198. $getopt->parse();
  199. } catch (Zend_Console_Getopt_Exception $e) {
  200. // Schlechte Option übergeben: Verwendung ausgeben
  201. echo $e->getUsageMessage();
  202. return false;
  203. }
  204. // Wenn Hilfe angefragt wurde, Verwendung ausgeben
  205. if ($getopt->getOption('h')) {
  206. echo $getopt->getUsageMessage();
  207. return true;
  208. }
  209. // Werte basierend auf Ihrer Anwesenheit oder Abwesenheit von CLI Optionen initialisieren
  210. $withData = $getopt->getOption('w');
  211. $env = $getopt->getOption('e');
  212. defined('APPLICATION_ENV')
  213. || define('APPLICATION_ENV', (null === $env) ? 'development' : $env);
  214. // Zend_Application initialisieren
  215. $application = new Zend_Application(
  216. APPLICATION_ENV,
  217. APPLICATION_PATH . '/configs/application.ini'
  218. );
  219. // Die DB Ressource initialisieren und empfangen
  220. $bootstrap = $application->getBootstrap();
  221. $bootstrap->bootstrap('db');
  222. $dbAdapter = $bootstrap->getResource('db');
  223. // Den Benutzer informieren was abgeht
  224. // (wir erstellen hier aktuell eine Datenbank)
  225. if ('testing' != APPLICATION_ENV) {
  226. echo 'Schreiben in die Guestbook Datenbank (control-c um abzubrechen): ' . PHP_EOL;
  227. for ($x = 5; $x > 0; $x--) {
  228. echo $x . "\r"; sleep(1);
  229. }
  230. }
  231. // Prüfen um zu sehen ob wie bereits eine Datenbankdatei haben
  232. $options = $bootstrap->getOption('resources');
  233. $dbFile = $options['db']['params']['dbname'];
  234. if (file_exists($dbFile)) {
  235. unlink($dbFile);
  236. }
  237. // Dieser Block führt die aktuellen Statements aus welche von der Schemadatei
  238. // geladen werden.
  239. try {
  240. $schemaSql = file_get_contents(dirname(__FILE__) . '/schema.sqlite.sql');
  241. // Die Verbindung direkt verwenden um SQL im Block zu laden
  242. $dbAdapter->getConnection()->exec($schemaSql);
  243. chmod($dbFile, 0666);
  244. if ('testing' != APPLICATION_ENV) {
  245. echo PHP_EOL;
  246. echo 'Datenbank erstellt';
  247. echo PHP_EOL;
  248. }
  249. if ($withData) {
  250. $dataSql = file_get_contents(dirname(__FILE__) . '/data.sqlite.sql');
  251. // Die Verbindung direkt verwenden um SQL in Blöcken zu laden
  252. $dbAdapter->getConnection()->exec($dataSql);
  253. if ('testing' != APPLICATION_ENV) {
  254. echo 'Daten geladen.';
  255. echo PHP_EOL;
  256. }
  257. }
  258. } catch (Exception $e) {
  259. echo 'EIN FEHLER IST AUFGETRETEN:' . PHP_EOL;
  260. echo $e->getMessage() . PHP_EOL;
  261. return false;
  262. }
  263. // Generell gesprochen wird dieses Skript von der Kommandozeile aus aufgerufen
  264. return true;
  265. ]]></programlisting>
  266. <para>
  267. Jetzt führen wir dieses Skript aus. Von einem Terminal oder der DOS Kommandozeile ist das
  268. folgende zu tun:
  269. </para>
  270. <programlisting language="shell"><![CDATA[
  271. % php scripts/load.sqlite.php --withdata
  272. ]]></programlisting>
  273. <para>
  274. Man sollte eine ähnliche Ausgabe wie folgt sehen:
  275. </para>
  276. <programlisting language="text"><![CDATA[
  277. path/to/ZendFrameworkQuickstart/scripts$ php load.sqlite.php --withdata
  278. Schreiben in die Guestbook Datenbank (control-c um abzubrechen):
  279. 1
  280. Datenbank erstellt
  281. Daten geladen.
  282. ]]></programlisting>
  283. <para>
  284. Jetzt haben wir eine voll funktionsfähige Datenbank und eine Tabelle für unsere Guestbook
  285. Anwendung. Unsere nächsten paar Schritte sind die Ausarbeitung unseres Anwendungscodes. Das
  286. inkludiert das Bauen einer Datenquelle (in unserem Fall verwenden wir
  287. <classname>Zend_Db_Table</classname>), und einen Daten Mapper um diese Datenquelle mit
  288. unserem Domain Modell zu verbinden. Letztendlich erstellen wir den Controller der mit diesem
  289. Modell interagiert damit sowohl existierende Einträge angezeigt als auch neue Einträge
  290. bearbeitet werden.
  291. </para>
  292. <para>
  293. Wir verwenden ein <ulink
  294. url="http://martinfowler.com/eaaCatalog/tableDataGateway.html">Table Data
  295. Gateway</ulink> um uns mit unserer Datenquelle zu verbinden;
  296. <classname>Zend_Db_Table</classname> bietet diese Funktionalität. Um anzufangen erstellen wir
  297. eine <classname>Zend_Db_Table</classname>-basierende Tabellenklasse. Zuerst erstellen wir
  298. das Verzeichnis <filename>application/models/DbTable/</filename>. Dann erstellen und
  299. bearbeiten wir die Datei <filename>Guestbook.php</filename> in Ihm und fügen die folgenden
  300. Inhalte ein:
  301. </para>
  302. <programlisting language="php"><![CDATA[
  303. // application/models/DbTable/Guestbook.php
  304. /**
  305. * Das ist die DbTable Klasse für die Guestbook Tabelle.
  306. */
  307. class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
  308. {
  309. /** Tabellenname */
  310. protected $_name = 'guestbook';
  311. }
  312. ]]></programlisting>
  313. <para>
  314. Der Klassenpräfix ist zu beachten: <classname>Application_Model_DbTable</classname>. Der
  315. Klassenpräfix für unser Modul "Application" ist das erste Segment, und dann haben wir die
  316. Komponente "Model_DbTable"; die letztere verweist auf das Verzeichnis
  317. <filename>models/DbTable/</filename> des Moduls.
  318. </para>
  319. <para>
  320. Alles das ist wirklich notwendig wenn <classname>Zend_Db_Table</classname> erweitert wird
  321. um einen Tabellennamen anzubieten und optional den primären Schlüssel (wenn es nicht die
  322. "id" ist).
  323. </para>
  324. <para>
  325. Jetzt erstellen wir einen <ulink
  326. url="http://martinfowler.com/eaaCatalog/dataMapper.html">Daten Mapper</ulink>. Ein
  327. <emphasis>Daten Mapper</emphasis> bildet ein Domain Objekt in der Datenbank ab. In unserem
  328. Fall bildet es unser Modell <classname>Application_Model_Guestbook</classname> auf unsere
  329. Datenquelle, <classname>Application_Model_DbTable_Guestbook</classname>, ab. Eine typische
  330. API für einen Daten Mapper ist wie folgt:
  331. </para>
  332. <programlisting language="php"><![CDATA[
  333. // application/models/GuestbookMapper.php
  334. class Application_Model_GuestbookMapper
  335. {
  336. public function save($model);
  337. public function find($id, $model);
  338. public function fetchAll();
  339. }
  340. ]]></programlisting>
  341. <para>
  342. Zusätzlich zu diesen Methoden, fügen wir Methoden für das Setzen und Holen des Table Data
  343. Gateways hinzu. Die endgültige Klasse, welche unter
  344. <filename>application/models/GuestbookMapper.php</filename> platziert ist, sieht wie folgt
  345. aus:
  346. </para>
  347. <programlisting language="php"><![CDATA[
  348. // application/models/GuestbookMapper.php
  349. class Application_Model_GuestbookMapper
  350. {
  351. protected $_dbTable;
  352. public function setDbTable($dbTable)
  353. {
  354. if (is_string($dbTable)) {
  355. $dbTable = new $dbTable();
  356. }
  357. if (!$dbTable instanceof Zend_Db_Table_Abstract) {
  358. throw new Exception('Ungültiges Table Data Gateway angegeben');
  359. }
  360. $this->_dbTable = $dbTable;
  361. return $this;
  362. }
  363. public function getDbTable()
  364. {
  365. if (null === $this->_dbTable) {
  366. $this->setDbTable('Application_Model_DbTable_Guestbook');
  367. }
  368. return $this->_dbTable;
  369. }
  370. public function save(Application_Model_Guestbook $guestbook)
  371. {
  372. $data = array(
  373. 'email' => $guestbook->getEmail(),
  374. 'comment' => $guestbook->getComment(),
  375. 'created' => date('Y-m-d H:i:s'),
  376. );
  377. if (null === ($id = $guestbook->getId())) {
  378. unset($data['id']);
  379. $this->getDbTable()->insert($data);
  380. } else {
  381. $this->getDbTable()->update($data, array('id = ?' => $id));
  382. }
  383. }
  384. public function find($id, Application_Model_Guestbook $guestbook)
  385. {
  386. $result = $this->getDbTable()->find($id);
  387. if (0 == count($result)) {
  388. return;
  389. }
  390. $row = $result->current();
  391. $guestbook->setId($row->id)
  392. ->setEmail($row->email)
  393. ->setComment($row->comment)
  394. ->setCreated($row->created);
  395. }
  396. public function fetchAll()
  397. {
  398. $resultSet = $this->getDbTable()->fetchAll();
  399. $entries = array();
  400. foreach ($resultSet as $row) {
  401. $entry = new Application_Model_Guestbook();
  402. $entry->setId($row->id)
  403. ->setEmail($row->email)
  404. ->setComment($row->comment)
  405. ->setCreated($row->created)
  406. ->setMapper($this);
  407. $entries[] = $entry;
  408. }
  409. return $entries;
  410. }
  411. }
  412. ]]></programlisting>
  413. <para>
  414. Jetzt ist es Zeit unsere Modellklasse leicht zu aktualisieren, um den Daten Mapper
  415. aufzunehmen. So wie der Daten Mapper eine Referenz zur Datenquelle enthält, enthält das
  416. Modell eine Referenz zum Daten Mapper. Zusätzlich machen wir es einfach das Modell
  417. bekanntzumachen indem ein Array an Daten entweder an den Constructor oder an die
  418. <methodname>setOptions()</methodname> Methode übergeben wird. Das endgültige Modell, welches
  419. in <filename>application/models/Guestbook.php</filename> ist, sieht wie folgt aus:
  420. </para>
  421. <programlisting language="php"><![CDATA[
  422. // application/models/Guestbook.php
  423. class Application_Model_Guestbook
  424. {
  425. protected $_comment;
  426. protected $_created;
  427. protected $_email;
  428. protected $_id;
  429. protected $_mapper;
  430. public function __construct(array $options = null)
  431. {
  432. if (is_array($options)) {
  433. $this->setOptions($options);
  434. }
  435. }
  436. public function __set($name, $value)
  437. {
  438. $method = 'set' . $name;
  439. if (('mapper' == $name) || !method_exists($this, $method)) {
  440. throw new Exception('Ungültige Guestbook Eigenschaft');
  441. }
  442. $this->$method($value);
  443. }
  444. public function __get($name)
  445. {
  446. $method = 'get' . $name;
  447. if (('mapper' == $name) || !method_exists($this, $method)) {
  448. throw new Exception('Ungültige Guestbook Eigenschaft');
  449. }
  450. return $this->$method();
  451. }
  452. public function setOptions(array $options)
  453. {
  454. $methods = get_class_methods($this);
  455. foreach ($options as $key => $value) {
  456. $method = 'set' . ucfirst($key);
  457. if (in_array($method, $methods)) {
  458. $this->$method($value);
  459. }
  460. }
  461. return $this;
  462. }
  463. public function setComment($text)
  464. {
  465. $this->_comment = (string) $text;
  466. return $this;
  467. }
  468. public function getComment()
  469. {
  470. return $this->_comment;
  471. }
  472. public function setEmail($email)
  473. {
  474. $this->_email = (string) $email;
  475. return $this;
  476. }
  477. public function getEmail()
  478. {
  479. return $this->_email;
  480. }
  481. public function setCreated($ts)
  482. {
  483. $this->_created = $ts;
  484. return $this;
  485. }
  486. public function getCreated()
  487. {
  488. return $this->_created;
  489. }
  490. public function setId($id)
  491. {
  492. $this->_id = (int) $id;
  493. return $this;
  494. }
  495. public function getId()
  496. {
  497. return $this->_id;
  498. }
  499. public function setMapper($mapper)
  500. {
  501. $this->_mapper = $mapper;
  502. return $this;
  503. }
  504. public function getMapper()
  505. {
  506. if (null === $this->_mapper) {
  507. $this->setMapper(new Application_Model_GuestbookMapper());
  508. }
  509. return $this->_mapper;
  510. }
  511. public function save()
  512. {
  513. $this->getMapper()->save($this);
  514. }
  515. public function find($id)
  516. {
  517. $this->getMapper()->find($id, $this);
  518. return $this;
  519. }
  520. public function fetchAll()
  521. {
  522. return $this->getMapper()->fetchAll();
  523. }
  524. }
  525. ]]></programlisting>
  526. <para>
  527. Letztendlich, um diese Elemente alle zusammen zu verbinden, erstellen wir einen Guestbook
  528. Controller der die Einträge auflistet welche aktuell in der Datenbank sind.
  529. </para>
  530. <para>
  531. Um einen neuen Controller zu erstellen muss ein Terminal oder eine DOS Konsole geöffnet,
  532. in das Projektverzeichnis navigiert und das folgende eingegeben werden:
  533. </para>
  534. <programlisting language="shell"><![CDATA[
  535. # Unix-artige Systeme:
  536. % zf.sh create controller guestbook
  537. # DOS/Windows:
  538. C:> zf.bat create controller guestbook
  539. ]]></programlisting>
  540. <para>
  541. Das erstellt einen neuen Controller, <classname>GuestbookController</classname>, in
  542. <filename>application/controllers/GuestbookController.php</filename> mit einer einzelnen
  543. Aktions Methode, <methodname>indexAction()</methodname>. Er erstellt auch ein View Skript
  544. Verzeichnis für den Controller, <filename>application/views/scripts/guestbook/</filename>,
  545. mit einem View Skript für die Index Aktion.
  546. </para>
  547. <para>
  548. Wir verwenden die "index" Aktion als Landeseite um alle Guestbook Einträge anzusehen.
  549. </para>
  550. <para>
  551. Jetzt betrachten wir die grundsätzliche Anwendungslogik. Bei einem Treffer auf
  552. <methodname>indexAction()</methodname> zeigen wir alle Guestbook Einträge an. Das würde wie
  553. folgt aussehen:
  554. </para>
  555. <programlisting language="php"><![CDATA[
  556. // application/controllers/GuestbookController.php
  557. class GuestbookController extends Zend_Controller_Action
  558. {
  559. public function indexAction()
  560. {
  561. $guestbook = new Application_Model_Guestbook();
  562. $this->view->entries = $guestbook->fetchAll();
  563. }
  564. }
  565. ]]></programlisting>
  566. <para>
  567. Und natürlich benötigen wir ein View Skript um damit weiterzumachen.
  568. <filename>application/views/scripts/guestbook/index.phtml</filename> ist zu bearbeiten damit
  569. Sie wie folgt aussieht:
  570. </para>
  571. <programlisting language="php"><![CDATA[
  572. <!-- application/views/scripts/guestbook/index.phtml -->
  573. <p><a href="<?php echo $this->url(
  574. array(
  575. 'controller' => 'guestbook',
  576. 'action' => 'sign'
  577. ),
  578. 'default',
  579. true) ?>">Im Guestbook eintragen</a></p>
  580. Guestbook Einträge: <br />
  581. <dl>
  582. <?php foreach ($this->entries as $entry): ?>
  583. <dt><?php echo $this->escape($entry->email) ?></dt>
  584. <dd><?php echo $this->escape($entry->comment) ?></dd>
  585. <?php endforeach ?>
  586. </dl>
  587. ]]></programlisting>
  588. <note>
  589. <title>Checkpoint</title>
  590. <para>
  591. Jetzt gehen wir auf "http://localhost/guestbook". Man sollte das folgende im Browser
  592. sehen:
  593. </para>
  594. <para>
  595. <inlinegraphic width="525" scale="100" align="center" valign="middle"
  596. fileref="figures/learning.quickstart.create-model.png" format="PNG" />
  597. </para>
  598. </note>
  599. <note>
  600. <title>Das Datenlade Skript verwenden</title>
  601. <para>
  602. Das Datenlade Skript welches in diesem Kapitel beschrieben wird
  603. (<filename>scripts/load.sqlite.php</filename>) kann verwendet werden um die Datenbank,
  604. für jede Umgebung die man definiert hat, zu erstellen sowie Sie mit Beispieldaten zu
  605. laden. Intern verwendet es <classname>Zend_Console_Getopt</classname>, was es erlaubt
  606. eine Anzahl von Kommandozeilen Schalter anzubieten. Wenn man den "-h" oder "--help"
  607. Schalter übergibt, werden die folgenden Optionen angegeben:
  608. </para>
  609. <programlisting language="php"><![CDATA[
  610. Usage: load.sqlite.php [ options ]
  611. --withdata|-w Datenbank mit einigen Daten laden
  612. --env|-e [ ] Anwendungsumgebung für welche die Datenbank erstellt wird
  613. (Standard ist Development)
  614. --help|-h Hilfe -- Verwendung)]]
  615. ]]></programlisting>
  616. <para>
  617. Der "-e" Schalter erlaubt es den Wert zu spezifizieren der für die Konstante
  618. <constant>APPLICATION_ENV</constant> verwendet wird -- welcher es erlaubt eine SQLite
  619. Datenbank für jede Umgebung zu erstellen die man definiert. Man sollte sicherstellen
  620. dass das Skript für die Umgebung gestartet wird welche man für die eigene Anwendung
  621. ausgewählt hat wenn man in Betrieb geht.
  622. </para>
  623. </note>
  624. </sect1>