Programmer's Reference Guide

Create A Layout

モデルとデータベーステーブルの作成

始める前にちょっと考えてみましょう。これらのクラスはどこにあって、それをどのように探すのでしょうか? わたしたちが作成したデフォルトのプロジェクトでは、一つのオートローダーがインスタンス化されます。 そこへ、他のクラスを探せるよう別のオートローダーを付け加えることができます。 MVC の様々なクラスはふつう一つのツリー -- ここでは application/ -- に集まっていて、ほとんどの場合には共通のプレフィックスを持っていてほしいものです。

Zend_Controller_Front は、独立したミニアプリケーション、 すなわち "モジュール" という考え方を採用しています。モジュールは zf ツールが application/ 以下に設定するディレクトリ構造を模倣しており、 その中の全てのクラスはモジュール名を共通のプレフィックスとして持っているものと見なされます。 application/ はそれ自体が一つのモジュール -- "default" または "application" モジュール -- です。以上を踏まえてこのディレクトリ下にあるリソースのオートロードを設定していきたいと思います。

Zend_Application_Module_Autoloader は、あるモジュールの様々なリソースを 適切なディレクトリに対応付けるために必要となる機能を提供し、同時に、名前の付け方の規約も提供します。 このクラスのインスタンスは、デフォルトではブートストラップ・オブジェクトの初期化時に作成され、 アプリケーションのブートストラップでは "Application" というプレフィックスをデフォルトで使用します。 そのため、モデル、フォーム、テーブル・クラスはどれも、プレフィックス "Application_" で始めます。

では、ゲストブックを作っていくことにしましょう。一般的にはコメントタイムスタンプ、それからたまにメールアドレスを持つ単純なリストになります。 それらをデータベースに保存するとしたら、各エントリーのユニークな識別子も欲しいかも知れません。 エントリーを保存したり特定のエントリーを取ってきたり全エントリーを読み出したくなることでしょう。 そうだとすると、簡単なゲストブックモデルの API はこのようになりそうです。

  1. // application/models/Guestbook.php
  2.  
  3. class Application_Model_Guestbook
  4. {
  5.     protected $_comment;
  6.     protected $_created;
  7.     protected $_email;
  8.     protected $_id;
  9.  
  10.     public function __set($name, $value);
  11.     public function __get($name);
  12.  
  13.     public function setComment($text);
  14.     public function getComment();
  15.  
  16.     public function setEmail($email);
  17.     public function getEmail();
  18.  
  19.     public function setCreated($ts);
  20.     public function getCreated();
  21.  
  22.     public function setId($id);
  23.     public function getId();
  24. }
  25.  
  26. class Application_Model_GuestbookMapper
  27. {
  28.     public function save(Application_Model_Guestbook $guestbook);
  29.     public function find($id);
  30.     public function fetchAll();
  31. }

__get()__set() は、 各エントリーのプロパティにアクセスする便利な仕組みと、他のゲッター、セッターのプロキシを提供してくれます。 また、オブジェクト中の許可したプロパティのみアクセス可能にするのにも役立ちます。

find()fetchAll() は単一のエントリーや 全てのエントリーをフェッチする機能を提供し、 save() は 一つのエントリーをデータストアに保存する面倒を見ます。

ここでようやく、データベース設定について考え始めることができます。

まず Db リソースを初期化する必要があります。 Layout リソースと View リソースから Db リソースの設定を準備できます。これには zf configure db-adapter コマンドが使えます。

  1. % zf configure db-adapter \
  2. > 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook.db"' \
  3. > production
  4. A db configuration for the production has been written to the application config file.
  5.  
  6. % zf configure db-adapter \
  7. > 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook-testing.db"' \
  8. > testing
  9. A db configuration for the production has been written to the application config file.
  10.  
  11. % zf configure db-adapter \
  12. > 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook-dev.db"' \
  13. > development
  14. A db configuration for the production has been written to the application config file.

ここで application/configs/application.ini ファイルの相当する部分に 以下の行が追加されているのが見付かるので、編集します。

  1. ; application/configs/application.ini
  2.  
  3. [production]
  4. ; ...
  5. resources.db.adapter = "PDO_SQLITE"
  6. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook.db"
  7.  
  8. [testing : production]
  9. ; ...
  10. resources.db.adapter = "PDO_SQLITE"
  11. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-testing.db"
  12.  
  13. [development : production]
  14. ; ...
  15. resources.db.adapter = "PDO_SQLITE"
  16. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-dev.db"

設定ファイルが最終的に以下のようになるようにしてください。

  1. ; application/configs/application.ini
  2.  
  3. [production]
  4. phpSettings.display_startup_errors = 0
  5. phpSettings.display_errors = 0
  6. bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
  7. bootstrap.class = "Bootstrap"
  8. appnamespace = "Application"
  9. resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
  10. resources.frontController.params.displayExceptions = 0
  11. resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
  12. resources.view[] =
  13. resources.db.adapter = "PDO_SQLITE"
  14. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook.db"
  15.  
  16. [staging : production]
  17.  
  18. [testing : production]
  19. phpSettings.display_startup_errors = 1
  20. phpSettings.display_errors = 1
  21. resources.db.adapter = "PDO_SQLITE"
  22. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-testing.db"
  23.  
  24. [development : production]
  25. phpSettings.display_startup_errors = 1
  26. phpSettings.display_errors = 1
  27. resources.db.adapter = "PDO_SQLITE"
  28. resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-dev.db"

データベースは data/db/ に保存されることに注意しましょう。 ディレクトリを作って全ユーザーに書き込み権限を与えます。ユニックスライクなシステムでは、 次のようにすれば設定できます。

  1. % mkdir -p data/db; chmod -R a+rwX data

Windows では、エクスプローラでディレクトリを作り、 全ユーザーがそのディレクトリに書き込めるようアクセス権を設定する必要があります。

この段階でデータベース接続が行えます。今の例では application/data/ ディレクトリ内にある Sqlite データベースへの接続です。では、ゲストブックのエントリーを入れる簡単なテーブルを設計しましょう。

  1. -- scripts/schema.sqlite.sql
  2. --
  3. -- この SQL からデータベーススキーマをロードする必要があります。
  4.  
  5. CREATE TABLE guestbook (
  6.     id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
  7.     email VARCHAR(32) NOT NULL DEFAULT 'noemail@test.com',
  8.     comment TEXT NULL,
  9.     created DATETIME NOT NULL
  10. );
  11.  
  12. CREATE INDEX "id" ON "guestbook" ("id");

それから、素晴らしい仕事ができるように、数行、アプリケーションを面白くするする情報を作りましょう。

  1. -- scripts/data.sqlite.sql
  2. --
  3. -- 以下の SQL 文でデータベースに生命を吹き込めます。
  4.  
  5. INSERT INTO guestbook (email, comment, created) VALUES
  6.     ('ralph.schindler@zend.com',
  7.     'Hello! Hope you enjoy this sample zf application!',
  8.     DATETIME('NOW'));
  9. INSERT INTO guestbook (email, comment, created) VALUES
  10.     ('foo@bar.com',
  11.     'Baz baz baz, baz baz Baz baz baz - baz baz baz.',
  12.     DATETIME('NOW'));

これでスキーマができ、データもいくらか定義できました。それでは一緒にスクリプトを書いてこのデータベースの構築を実行しましょう。 普通は、プロダクション環境でこういったことは必要ありませんが、このスクリプトがあれば開発者が必要なデータベースを手元で構築して、アプリケーションの作業に全力投球するのを助けてくれるでしょう。 以下の内容で、scripts/load.sqlite.php としてスクリプトを作ってください。

  1. // scripts/load.sqlite.php
  2.  
  3. /**
  4. * データベースを作成して読み込むスクリプト
  5. */
  6.  
  7. // アプリケーションパスとオートロードの初期化
  8. defined('APPLICATION_PATH')
  9.     || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
  10. set_include_path(implode(PATH_SEPARATOR, array(
  11.     APPLICATION_PATH . '/../library',
  12. )));
  13. require_once 'Zend/Loader/Autoloader.php';
  14. Zend_Loader_Autoloader::getInstance();
  15.  
  16. // CLI 用のオプション
  17. $getopt = new Zend_Console_Getopt(array(
  18.     'withdata|w' => 'Load database with sample data',
  19.     'env|e-s'    => 'Application environment for which to create database (defaults to development)',
  20.     'help|h'     => 'Help -- usage message',
  21. ));
  22. try {
  23.     $getopt->parse();
  24. } catch (Zend_Console_Getopt_Exception $e) {
  25.     // オプションが不正な場合に使用法を表示
  26.     echo $e->getUsageMessage();
  27.     return false;
  28. }
  29.  
  30. // ヘルプが要求された場合に使用法を表示
  31. if ($getopt->getOption('h')) {
  32.     echo $getopt->getUsageMessage();
  33.     return true;
  34. }
  35.  
  36. // CLI オプションの有無に応じて値を初期化
  37. $withData = $getopt->getOption('w');
  38. $env      = $getopt->getOption('e');
  39. defined('APPLICATION_ENV')
  40.     || define('APPLICATION_ENV', (null === $env) ? 'development' : $env);
  41.  
  42. // Zend_Application の初期化
  43. $application = new Zend_Application(
  44.     APPLICATION_ENV,
  45.     APPLICATION_PATH . '/configs/application.ini'
  46. );
  47.  
  48. // DB リソースの初期化と読み込み
  49. $bootstrap = $application->getBootstrap();
  50. $bootstrap->bootstrap('db');
  51. $dbAdapter = $bootstrap->getResource('db');
  52.  
  53. // やっていることをユーザーに通知
  54. // (実際にここでデータベースを作る)
  55. if ('testing' != APPLICATION_ENV) {
  56.     echo 'Writing Database Guestbook in (control-c to cancel): ' . PHP_EOL;
  57.     for ($x = 5; $x > 0; $x--) {
  58.         echo $x . "\r"; sleep(1);
  59.     }
  60. }
  61.  
  62. // データベースファイルが既にないかチェック
  63. $options = $bootstrap->getOption('resources');
  64. $dbFile  = $options['db']['params']['dbname'];
  65. if (file_exists($dbFile)) {
  66.     unlink($dbFile);
  67. }
  68.  
  69. // このブロックでスキーマファイルから読み込んだ実際のステートメントを実行
  70. try {
  71.     $schemaSql = file_get_contents(dirname(__FILE__) . '/schema.sqlite.sql');
  72.     // use the connection directly to load sql in batches
  73.     $dbAdapter->getConnection()->exec($schemaSql);
  74.     chmod($dbFile, 0666);
  75.  
  76.     if ('testing' != APPLICATION_ENV) {
  77.         echo PHP_EOL;
  78.         echo 'Database Created';
  79.         echo PHP_EOL;
  80.     }
  81.  
  82.     if ($withData) {
  83.         $dataSql = file_get_contents(dirname(__FILE__) . '/data.sqlite.sql');
  84.         // use the connection directly to load sql in batches
  85.         $dbAdapter->getConnection()->exec($dataSql);
  86.         if ('testing' != APPLICATION_ENV) {
  87.             echo 'Data Loaded.';
  88.             echo PHP_EOL;
  89.         }
  90.     }
  91.  
  92. } catch (Exception $e) {
  93.     echo 'AN ERROR HAS OCCURED:' . PHP_EOL;
  94.     echo $e->getMessage() . PHP_EOL;
  95.     return false;
  96. }
  97.  
  98. // 大抵の場合、このスクリプトはコマンドラインから走らせて true を返す

このスクリプトを実行しましょう。ターミナルか DOS のコマンドラインから以下を実行してください。

  1. % php scripts/load.sqlite.php --withdata

以下のような出力を目にすると思います。

  1. path/to/ZendFrameworkQuickstart/scripts$ php load.sqlite.php --withdata
  2. Writing Database Guestbook in (control-c to cancel):
  3. 1
  4. Database Created
  5. Data Loaded.

これでゲストブックアプリケーションのためにきちんと動くデータベースとテーブルができました。 次のステップはアプリケーションのコードを作成することです。 これにはデータソース(ここでは Zend_Db_Table を使います)と、 そのデータソースをドメインモデルに繋げる役目のデータマッパーを構築することが含まれます。 最後に、既存のエントリーの表示と新規エントリーの処理をモデルに結び付けるコントローラーも作ります。

ここではデータソースへの接続に» テーブルデータゲートウェイ を使います。 Zend_Db_Table がこの機能を提供してくれます。 始めるにあたって Zend_Db_Table ベースのクラスを作りましょう。 レイアウトとデータベースアダプタでやった時と同じように、zf ツールの力を借りることができます。create db-table コマンドを使うのです。 これは最低で 2 つの引数をとります。参照させるクラスと、対応付けるデータベーステーブルの名前です。

  1. % zf create db-table Guestbook guestbook
  2. Creating a DbTable at application/models/DbTable/Guestbook.php
  3. Updating project profile 'zfproject.xml'

ディレクトリツリーを見てみると、新規ディレクトリ application/models/DbTable/ が作られてファイル Guestbook.php が作られているのが分かります。 ファイルを開くと以下の内容になっています。

  1. // application/models/DbTable/Guestbook.php
  2.  
  3. /**
  4. * This is the DbTable class for the guestbook table.
  5. */
  6. class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
  7. {
  8.     /** Table name */
  9.     protected $_name    = 'guestbook';
  10. }

クラスのプレフィックス Application_Model_DbTable に注目しましょう。 最初の部分がモジュールのクラスプレフィックス "Application" で、その後にコンポーネント "Model_DbTable" がきます。後者はモジュールのディレクトリ models/DbTable/ に対応付けられています。

Zend_Db_Table を拡張する際に必要なのはテーブル名と場合により主キーを ("id" でなければ)与えることだけです。

では » データマッパー を作成しましょう。データマッパー はドメインオブジェクトをデータベースに対応付けます。 ここではモデル Application_Model_Guestbook をデータソース Application_Model_DbTable_Guestbook に対応付けることになります。 データマッパーの典型的な API は次のようになるでしょう。

  1. // application/models/GuestbookMapper.php
  2.  
  3. class Application_Model_GuestbookMapper
  4. {
  5.     public function save($model);
  6.     public function find($id, $model);
  7.     public function fetchAll();
  8. }

こうしたメソッドの他に、テーブルデータゲートウェイを設定してそこからデータを取り出すメソッドを追加します。 クラスの最初の形を作成するのに CLI の zf ツールを使います。

  1. % zf create model GuestbookMapper
  2. Creating a model at application/models/GuestbookMapper.php
  3. Updating project profile '.zfproject.xml'

次に application/models/GuestbookMapper.php にあるクラス Application_Model_GuestbookMapper を編集して下記の通りにします。

  1. // application/models/GuestbookMapper.php
  2.  
  3. class Application_Model_GuestbookMapper
  4. {
  5.     protected $_dbTable;
  6.  
  7.     public function setDbTable($dbTable)
  8.     {
  9.         if (is_string($dbTable)) {
  10.             $dbTable = new $dbTable();
  11.         }
  12.         if (!$dbTable instanceof Zend_Db_Table_Abstract) {
  13.             throw new Exception('Invalid table data gateway provided');
  14.         }
  15.         $this->_dbTable = $dbTable;
  16.         return $this;
  17.     }
  18.  
  19.     public function getDbTable()
  20.     {
  21.         if (null === $this->_dbTable) {
  22.             $this->setDbTable('Application_Model_DbTable_Guestbook');
  23.         }
  24.         return $this->_dbTable;
  25.     }
  26.  
  27.     public function save(Application_Model_Guestbook $guestbook)
  28.     {
  29.         $data = array(
  30.             'email'   => $guestbook->getEmail(),
  31.             'comment' => $guestbook->getComment(),
  32.             'created' => date('Y-m-d H:i:s'),
  33.         );
  34.  
  35.         if (null === ($id = $guestbook->getId())) {
  36.             unset($data['id']);
  37.             $this->getDbTable()->insert($data);
  38.         } else {
  39.             $this->getDbTable()->update($data, array('id = ?' => $id));
  40.         }
  41.     }
  42.  
  43.     public function find($id, Application_Model_Guestbook $guestbook)
  44.     {
  45.         $result = $this->getDbTable()->find($id);
  46.         if (0 == count($result)) {
  47.             return;
  48.         }
  49.         $row = $result->current();
  50.         $guestbook->setId($row->id)
  51.                   ->setEmail($row->email)
  52.                   ->setComment($row->comment)
  53.                   ->setCreated($row->created);
  54.     }
  55.  
  56.     public function fetchAll()
  57.     {
  58.         $resultSet = $this->getDbTable()->fetchAll();
  59.         $entries   = array();
  60.         foreach ($resultSet as $row) {
  61.             $entry = new Application_Model_Guestbook();
  62.             $entry->setId($row->id)
  63.                   ->setEmail($row->email)
  64.                   ->setComment($row->comment)
  65.                   ->setCreated($row->created);
  66.             $entries[] = $entry;
  67.         }
  68.         return $entries;
  69.     }
  70. }

これでモデルクラスが作れます。ここでもコマンド zf create model を使います。

  1. % zf create model Guestbook
  2. Creating a model at application/models/Guestbook.php
  3. Updating project profile '.zfproject.xml'

この空の PHP クラスを修正して、コンストラクタでも setOptions() メソッドでも、データの配列からモデルを生成するのを簡単にします。application/models/Guestbook.php 中の最終的なモデルクラスはこのようになるはずです。

  1. // application/models/Guestbook.php
  2.  
  3. class Application_Model_Guestbook
  4. {
  5.     protected $_comment;
  6.     protected $_created;
  7.     protected $_email;
  8.     protected $_id;
  9.  
  10.     public function __construct(array $options = null)
  11.     {
  12.         if (is_array($options)) {
  13.             $this->setOptions($options);
  14.         }
  15.     }
  16.  
  17.     public function __set($name, $value)
  18.     {
  19.         $method = 'set' . $name;
  20.         if (('mapper' == $name) || !method_exists($this, $method)) {
  21.             throw new Exception('Invalid guestbook property');
  22.         }
  23.         $this->$method($value);
  24.     }
  25.  
  26.     public function __get($name)
  27.     {
  28.         $method = 'get' . $name;
  29.         if (('mapper' == $name) || !method_exists($this, $method)) {
  30.             throw new Exception('Invalid guestbook property');
  31.         }
  32.         return $this->$method();
  33.     }
  34.  
  35.     public function setOptions(array $options)
  36.     {
  37.         $methods = get_class_methods($this);
  38.         foreach ($options as $key => $value) {
  39.             $method = 'set' . ucfirst($key);
  40.             if (in_array($method, $methods)) {
  41.                 $this->$method($value);
  42.             }
  43.         }
  44.         return $this;
  45.     }
  46.  
  47.     public function setComment($text)
  48.     {
  49.         $this->_comment = (string) $text;
  50.         return $this;
  51.     }
  52.  
  53.     public function getComment()
  54.     {
  55.         return $this->_comment;
  56.     }
  57.  
  58.     public function setEmail($email)
  59.     {
  60.         $this->_email = (string) $email;
  61.         return $this;
  62.     }
  63.  
  64.     public function getEmail()
  65.     {
  66.         return $this->_email;
  67.     }
  68.  
  69.     public function setCreated($ts)
  70.     {
  71.         $this->_created = $ts;
  72.         return $this;
  73.     }
  74.  
  75.     public function getCreated()
  76.     {
  77.         return $this->_created;
  78.     }
  79.  
  80.     public function setId($id)
  81.     {
  82.         $this->_id = (int) $id;
  83.         return $this;
  84.     }
  85.  
  86.     public function getId()
  87.     {
  88.         return $this->_id;
  89.     }
  90. }

最後に、以上の要素を全て一つに繋げます。データベース内の既存のエントリーを一覧表示する ゲストブック用のコントローラを作りましょう。

新しいコントローラを作るには zf create controller コマンドを使います。

  1. % zf create controller Guestbook
  2. Creating a controller at
  3.     application/controllers/GuestbookController.php
  4. Creating an index action method in controller Guestbook
  5. Creating a view script for the index action method at
  6.     application/views/scripts/guestbook/index.phtml
  7. Creating a controller test file at
  8.     tests/application/controllers/GuestbookControllerTest.php
  9. Updating project profile '.zfproject.xml'

このコマンドによって application/controllers/GuestbookController.php の中に GuestbookController が作られ、そこには一つのアクションメソッド indexAction() が出来ています。また、このコントローラーの ビュースクリプト用ディレクトリ application/views/scripts/guestbook/ とインデックスアクション用のビュースクリプトも作成されます。

ゲスブックの全エントリーを表示する入り口用のページとして "index" アクションを使います。

では、基本的なアプリケーションロジックを一息に作ってしまいましょう。 indexAction() へやって来るとゲストブックの全エントリーを表示します。これは次のようになります。

  1. // application/controllers/GuestbookController.php
  2.  
  3. class GuestbookController extends Zend_Controller_Action
  4. {
  5.     public function indexAction()
  6.     {
  7.         $guestbook = new Application_Model_GuestbookMapper();
  8.         $this->view->entries = $guestbook->fetchAll();
  9.     }
  10. }

それからもちろんこれに使うビュースクリプトが必要です。 application/views/scripts/guestbook/index.phtml を以下のように編集します。

  1. <!-- application/views/scripts/guestbook/index.phtml -->
  2.  
  3. <p><a href="<?php echo $this->url(
  4.     array(
  5.         'controller' => 'guestbook',
  6.         'action'     => 'sign'
  7.     ),
  8.     'default',
  9.     true) ?>">Sign Our Guestbook</a></p>
  10.  
  11. Guestbook Entries: <br />
  12. <dl>
  13.     <?php foreach ($this->entries as $entry): ?>
  14.     <dt><?php echo $this->escape($entry->email) ?></dt>
  15.     <dd><?php echo $this->escape($entry->comment) ?></dd>
  16.     <?php endforeach ?>
  17. </dl>

注意: チェックポイント
ここで "http://localhost/guestbook" にアクセスしてみましょう。 ブラウザには次のように表示されるはずです。

learning.quickstart.create-model.png

注意: データローダースクリプトの使用
この節で導入したデータローダースクリプト(scripts/load.sqlite.php)は 定義した環境のそれぞれでデータベースを作りサンプルデータを読み込むのに使用できます。 内部では、多くのコマンドラインスイッチを提供できるようにしてくれる Zend_Console_Getopt を利用しています。"-h" または "--help" スイッチを渡すと使用可能なオプションを提示します。

  1. Usage: load.sqlite.php [ options ]
  2. --withdata|-w         Load database with sample data
  3. --env|-e [  ]         Application environment for which to create database
  4.                       (defaults to development)
  5. --help|-h             Help -- usage message]]
"-e" スイッチを使うと APPLICATION_ENV 定数に使用する値を指定できます。 -- 定義した各環境で順に SQLite データベースを作れるようになるのです。 デプロイ時に、アプリケーション用に選んだ環境で確実にこのスクリプトを走らせるようにしてください。


Create A Layout

Comments

The example configuring the database adapter with zf configure db-adapter does not work for me running the command from both NetBeans IDE and Windows 7 command prompt.

Executing the command as:

zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH \"/../data/db/guestbook.db\"" -s production

zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH \"/../data/db/guestbook-testing.db\"" -s testing

works, but writes
resources.db.params.dbname = "APPLICATION_PATH /../data/db/guestbook.db"
to the configuration, which ofcourse should be
resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook.db"

Also, trying to configure the development section php raises a notice and does not configure anything (even though it said it did)

PHP Notice:  Undefined offset: 28 in C:\Program Files (x86)\Zend\ZendServer\share\ZendFramework\library\Zend\Tool\Project\Provider\DbAdapter.php on line 182

So if you're finding problems with this, for now just manually add the lines to your application.ini

I had the following problem: when I accessed the guestbook controller it showed an error:

Fatal error: Class 'Application_Model_GuestbookMapper' not found in path\to\quickstart\application\controllers\GuestbookController.php on line 13

After some time of searching the web I found a solution. Just add this to your Bootstrap.php, at the end of the _initDoctype function:

$loader = new Zend_Loader_Autoloader_Resource (array (
'basePath' => APPLICATION_PATH,
'namespace' => 'Application',
));

$loader -> addResourceType ( 'model', 'models', 'Model');
When executing the load.sqlite.php (on a Windows machine) it would fail to work and just output the script to the console.

To make it work I had to add the <?php and ?> tags to the beginning and end of the script like so below:


<?php
// scripts/load.sqlite.php

...

// generally speaking, this script will be run from the command line
return true;
?>
/GuestbookMapper.php
<pre>
if (null === ($id = $guestbook->getId())) {

unset($data['id']); //<--- this should be unset($data[$id]);

$this->getDbTable()->insert($data);

} else {

$this->getDbTable()->update($data, array('id = ?' => $id));

}

</pre>
I wish there was an alternative version of this tutorial that used MySQL.
If you carefully follow all the steps it is working fine but two things are missing here.

In a regular php installation the pdo_sqlite is not enable. Make sure this is set in your php.ini file.

Second and in case you get this following error when you run the Guestbook:
SQLSTATE[HY000] [14] unable to open database file

For some reason the DB folder and files need to be inside the /public/ folder which isn't mentioned as far as I can see.
And for the zf configure db-adapter in Windows I forgot to mention:

Reverse the quotation marks
Hence this:
'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook.db"'

should be this
"adapter=PDO_SQLITE&dbname=APPLICATION_PATH '/../data/db/guestbook.db'"
Missing an image after this text:

Note: Checkpoint
Now browse to "http://localhost/guestbook". You should see the following in your browser:
Just to clarify. These are the commands that worked for me in Windows XP:

zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH '/../data/db/guestbook.db'" -s production
zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH '/../data/db/guestbook-testing.db'" -s testing
zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH '/../data/db/guestbook-dev.db'" -s development


Also, the data folder should go in the same directory as application directory is, not inside the application directory.
@adrian >> For some reason the DB folder and files need to be inside the /public/ folder which isn't mentioned as far as I can see.

you're wrong about the fact that db folder needs to be in /public/ folder & you're wrong about the fact it's not mentioned.

i invite you to look better :)

anyway, i'm on mac os and have no problem.

for people didn't see that php tags where missing maybe you have to pay more attention what you're doing and not just copy/paste what you see :) the load file is a php script ;)

@tchaOo°
@adrian >> For some reason the DB folder and files need to be inside the /public/ folder which isn't mentioned as far as I can see.

you're wrong about the fact that db folder needs to be in /public/ folder & you're wrong about the fact it's not mentioned.

i invite you to look better :)

anyway, i'm on mac os and have no problem.

for people didn't see that php tags where missing maybe you have to pay more attention what you're doing and not just copy/paste what you see :) the load file is a php script ;)

@tchaOo°
I've got the same error:
Fatal error: Class 'Application_Model_Guestbook' not found in...

I've found the following solution:

// Add this method to your Bootstrap class

protected function _initAutoload()
{
$loader = new Zend_Application_Module_Autoloader(array(
'namespace' => 'Application',
'basePath' => APPLICATION_PATH
));
return $loader;
}
I just wonder why creating a class "GuestbookMapper" instead of using the rowClass attribute in DbTable_Guestbook and have the class Guessbook extending Zend_Db_Table_Row_Abstract ?
Hello,
Is anyone could explain the way how apache server will proceed request http://zendtest.local/guestbook?
I have problem, my server show OK for http://zendtest.local, http://zendtest.local/guestbook bring me:
The requested URL /guestbook was not found on this server.
I have been playing with parameters of httpd.conf, but nothing good...
The main thing I do not understand how server should know that such request actiolly should be shown index of view of guestbook?
Thank you in advance.
zf configure db-adapter "adapter=MySQLi&dbname=zend&username=root&password=12&charset=utf8"
don't know why this tutorial does not mention creating the db connection to a mysql db. pdo_sqlite does not come working by default. You have to include like four different pdo* libraries in your .ini file to make this work. There is nothing in this article about setting this up. It required me to search like an hour to find this info. Very poorly written tutorial.

to use mysql instead of sqlite i found this somewhere to add to application.ini

resources.db.adapter = "PDO_MYSQL"
resources.db.params.host = "localhost"
resources.db.params.username = "mysqlusername"
resources.db.params.password = "mysqlpassword"
resources.db.params.dbname = "dbname"

I just added this to each production, development and testing sections.

so I skipped the whole create db script and just executed the sql in navicat.

my question is do we need to run elements of that load.sqlite.sql even for a existing mysql db to make the connection work?

I created all the model, view mapper etc.... Got to the end and now get a 404 error saying it cant even find guestbook







I was having trouble running the CLI file scripts/load.sqlite.php with messages about not finding several files. It turns out it was that the CLI was using a different php.ini than the main zend php.ini, so I created a symbolic link from the one the CLI found to the correct one: sudo ln -s /usr/local/zend/etc/php.ini /etc/php5/cli/php.ini

This fixed the problem.
andy
"to use mysql instead of sqlite i found this somewhere to add to application.ini"

You did right, it should work, it works for me.

You don´t need to run load.sqlite.sql at all.

Check every other step in case you missed something. Don´t forget to name your database and tables correctly and to grant all privileges to yourself. Check in your apache settings if rewrite_module is enabled, otherwise you'll get 404 errors in all actions other than IndexAction.
Another half-ased written tutorial that makes you frustrated because you have to search for answers to the holes it leaves open.

Why do people write tutorials as if you are supposed to know what they are talking about?

After all, we came to learn, not guess!
Another half-ased written tutorial that makes you frustrated because you have to search for answers to the holes it leaves open.

Why do people write tutorials as if you are supposed to know what they are talking about?

After all, we came to learn, not guess!
for people who are getting 404/505 at 'http://localhost/guestbook'
.htaccess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]

in your /path/to/quickstart/public/
it worked on my pc.

I think it's better to remove comment line "application/models/Guestbook.php" from first code block, because now it's look like user shoud create this file and paste the mentioned code there (both classes). However it's only description of interface, which we will implement later.
I added this code in application.ini

resources.db.adapter = "PDO_MYSQL"
resources.db.params.host = "localhost"
resources.db.params.username = "mysqlusername"
resources.db.params.password = "mysqlpassword"
resources.db.params.dbname = "dbname"

It works:)
Como faço para buscar dois campos, por exemplo:
Controller:
function searchAction(){
//mostrar o form de pesquisa
}

function viewAction(){
//pega os dados passados e faz a pesquisa no bando dados
$resultado = model->getSearch($nome, $cidade);
$this->view->resultado = $resultado;
}

Model:
function getSearch($nome, $cidade){

??????

return $result;
}
I went with pdo_mysql, with the following zf commands.

zf configure db-adapter 'adapter=Pdo_Mysql&host=localhost&username=name&password=pass&dbname=APPLICATION_PATH "/../data/db/guestbook.db"' production

zf configure db-adapter 'adapter=Pdo_Mysql&host=localhost&username=name&password=pass&dbname=APPLICATION_PATH "/../data/db/guestbook-testing.db"' test

zf configure db-adapter 'adapter=Pdo_Mysql&host=localhost&username=name&password=pass&dbname=APPLICATION_PATH "/../data/db/guestbook-dev.db"' development

Hope this helps someone else not get as confused as I was.


Two tips:

1. Note that the database(s) will be stored in data/db/. Create those directories, and make them world-writeable. On unix-like systems, you can do that as...

Instead of making these directories world-writeable, use the web server processes user (defined in the User and Group directive in Apache as daemon or www-data) for the directory's user and group, as they will be the PHP process effective user and group. Try the following:

$ pwd
/usr/local/apache/htdocs/example/application
$ sudo chown daemon.daemon data/db


2. In the Application_Model_Guestbook class __get() and __set() magic methods defines that getters and setters might be defines as getproperty() instead of getProperty. If you use getPropertyName and setProperty flavor, change the first line in the magic methods to:

$method = 'get' . ucfirst($name)

and

$method = 'set' . ucfirst($name)

Hi everyone,

I had trouble adapting this to Microsoft SQL Server. I figured it out eventually.

Here is what you do:

1. Make sure MSSQL works normally with a simple php file.
2. Now to use it with Zend, have the application.ini file look like this:
resources.db.adapter = "sqlsrv"
resources.db.params.host = "***.***.***.***"
resources.db.params.dbname = "Database"
resources.db.params.username = "*******"
resources.db.params.password = "*******"

It should be this simple (hopefully). But also note that youll probably have to create the database and stuff on your own, this is mainly for the important part (i.e. connection to the database for use with other parts of the tutorial).

note: I am on windows server 2008 using IIS7 and Sql Server 2008
MySQL, not SQLITE, is standard nowdays, but editing the .ini file with those lines dose the job for MySQL users:

resources.db.adapter = "PDO_MYSQL"
resources.db.params.host = "localhost"
resources.db.params.username = "mysqlusername"
resources.db.params.password = "mysqlpassword"
resources.db.params.dbname = "dbname"

The problem not addressed here is: how do I access data across more then one database? I need a sort of multiadapter for a JOIN that includes a clause like:
db1.table1.id = db2.table1.id

As this example makes the mapping a dependent class?
If anyone is having trouble understanding the zf configure db-adapter because they are getting the response "Nothing to do!", note that the first line is meant to be read as:

zf configure db-adapter \

Once that is entered you will notice the ">" on the left, that matches the ">" in this tutorial...just keep copying and pasting till the next ">" and you'll be great!
Hello again,

If anyone is unsure of where to put the DB (php and sql) files, you must make a "scripts" folder in your root (quickstart) folder.

Name the files without "scripts/" in front and let the terminal take over
In the data mapper, the find() and fetchAll() methods could be simplified by making use of the toArray() method of Zend_Db_Table_Row_Abstract:

$entry->setOptions($row->toArray());

This also would eliminate the need to modify the find() and fetchAll() methods if the table structure changes during development. And had it not been for the created field that the save() method sets to the current datetime, one could implement a toArray() method in the model and use it to initialize $data in the save() method, which would eliminate the need to modify any part of the mapper if the table structure changes. Plus, the same mapper code could then be used for all models in the application. Or would any of that be considered in any way bad practice?

Another suggestion I have is to expand the if condition in the save() method such that the insert occurs if $id is null or 0. This would make life easier when implementing an editAction() in the controller.

Youssef Eldakar
Bibliotheca Alexandrina
for MySQL:


CREATE TABLE guestbook (
  id int(11) NOT NULL AUTO_INCREMENT,
  email varchar(32) NOT NULL DEFAULT 'noemail@test.com',
  `comment` text,
  created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)




INSERT INTO guestbook (email, comment, created) VALUES
    ('ralph.schindler@zend.com',
    'Hello! Hope you enjoy this sample zf application!',
    NOW()),
    ('foo@bar.com',
    'Baz baz baz, baz baz Baz baz baz - baz baz baz.',
    NOW());

for MySQL:


CREATE TABLE guestbook (
  id int(11) NOT NULL AUTO_INCREMENT,
  email varchar(32) NOT NULL DEFAULT 'noemail@test.com',
  `comment` text,
  created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)




INSERT INTO guestbook (email, comment, created) VALUES
    ('ralph.schindler@zend.com',
    'Hello! Hope you enjoy this sample zf application!',
    NOW()),
    ('foo@bar.com',
    'Baz baz baz, baz baz Baz baz baz - baz baz baz.',
    NOW());

I see two problems on this page.

First, the chapter opens with the idea of specifying a prefix ("Application_") to the class files generated by the zf tool, but there's a procedure to cause that to happen, and someone forgot to write it up (?). So far my application.ini is similar to the one shown after the db adapter configuration, but when I create the database table class its class name is Model_DbTable_Guestbook instead of Application_Model_DbTable_Guestbook. It's not too much work to add the prefix manually, but clearly it's not the way things are supposed to work at this point.

Also, the code for the GuestbookMapper class is repeated, it appears first in application/model/Guestbook.php, and then again on its own. I'm pretty sure it should only show up in its own file.
Comment 1

Regarding the "Fatal error: Class 'Application_Model_Guestbook' not found in..." problem, I encountered it too. Plamena marinova's solution above is the answer, not Joao Portelo's, because it makes clear what you are doing - initialising the autoloader, not the document type, although well done Joao for tracking down the required lines of code.

Comment 2

I also had a problem with the class Model_Db_Table_Guestbook not being found. When I used,

zf create db-table Guestbook guestbook

the class that was created was Model_DbTable_Guestbook and not Application_Model_DbTable_Guestbook, with the result that the autoloader was unable to find it.

Changing all references to the class to include the Application_ prefix made it work.

I am using Zend Framework 1.10.7. Is this a bug? If not, is there a different fix?

At least in Zend Framework 1.10.3, which is what I am currently using, the error controller's error action view script that the zf command generates is a full HTML with <html> and </html>, not a layout segment like other view scripts in this quick start. Thus, when layout is enabled, error pages become misformatted as they contain two <html> tags and two </html> tags. To correct this, insert the following right at the beginning of ErrorController::errorAction():

$this->view->layout()->disableLayout();

Youssef Eldakar
Bibliotheca Alexandrina


thanx for that Youssef Eldakar :)
Just a fix for another comment:

@Finau Kaufusi on: 2010-02-20 16:50:38


/GuestbookMapper.php
<pre>
if (null === ($id = $guestbook->getId())) {
unset($data['id']); //<--- this should be unset($data[$id]);
$this->getDbTable()->insert($data);
}


The "unset($data['id'])" is correct. If it should be $id it would be null so that the code "unset($data[null])" wouldn't make sense.

Sidtj
Sumaré, SP, Brazil
Thank you for a fantastic tutorial. I've developed more than my share of applications deeep into unmanagability using homespun ideas and patchwork frameworks. I look forward to giving this framework a try.

Application_Model_Page::__set, __get and setOptions are particularly brilliant and instructional. They are generic enough to abstract out into their own Model Parent class and use with any tables that require field based access. Is there a recommended way to do this that fits tightly into the Zend architecture?

My first inclination is to the create a ZendExtensions directory next to the Zend directory in the library, then subpath based on the Zend namespace to keep it all organized (ie: ZendExtensions/Model/ModelExtension.php).

Does this parallel directory structure make sense? Should I contribute ideas like this to the community instead?

Thanks again,
David
Thank you for a fantastic tutorial. I've developed more than my share of applications deeep into unmanagability using homespun ideas and patchwork frameworks. I look forward to giving this framework a try.

Application_Model_Page::__set, __get and setOptions are particularly brilliant and instructional. They are generic enough to abstract out into their own Model Parent class and use with any tables that require field based access. Is there a recommended way to do this that fits tightly into the Zend architecture?

My first inclination is to the create a ZendExtensions directory next to the Zend directory in the library, then subpath based on the Zend namespace to keep it all organized (ie: ZendExtensions/Model/ModelExtension.php).

Does this parallel directory structure make sense? Should I contribute ideas like this to the community instead?

Thanks again,
David
Note that when doing this for MySQL or other non-sqllite db, you do not need to create the data folder or set the file path in zf configure command. You need to specify the database name, host, user, and password. Also, there is no need to repeat those elements that are the same for different configurations. For example:

zf configure db-adapter "adapter=PDO_MYSQL&dbname=crowdom&host=localhost&username=crowdom_user&password=crowdom_password" production

zf configure db-adapter "dbname=crowdom-test&username=test_user&password=test_password" testing

zf configure db-adapter "dbname=crowdom-dev&username=dev_user&password=dev_password" development

Stop it. Just stop.
http://www.joelonsoftware.com/items/2009/09/23.html
http://www.joelonsoftware.com/articles/fog0000000018.html

it's ridiculous how intead of saying "create a file and put this inside", the author try to automate things with autogenerating scripts...
instead of saying "execute sqlite 3 < schema.sql", it writes a complicated php script to do the same...
So, where is the 'intro' to zend framework.

To me it seems that I first have to finish my master of computer science to understand this tutorial.

And the 30 minutes (as said at the beginning of this mess) have passed some hours ago.

What worth is a tutorial, when there are obviously mistakes in it, so that you get stuck at least twice a page? And placing the correct lines of code in the comment section is not helpful.

My first impression of zend: complicate and just frustrating

At this point I will quit this
and try a piece of cake(php) or some fat free framework.

Bye and good luck

Is it ok to check in mapper's save:


if (null === ($id = $guestbook->getId()))
// ^^^^^^^


while in the model we have:


public function setId($id)
{
        $this->_id = (int) $id;
//                     ^^^^^^^
        return $this;
}
[code]
Just a question ;> 

http://pl.php.net/manual/en/language.types.null.php
I followed the tutoriel carefully.
I have something when I go to http://localhost:portNumber
but when I add http://localhost:portNumber/guestbook I have a 500 error.
There is nothing in the error.log or access.log.
I've still tried what said Plamena Marinova but it doesn't work for me.
Any clue?
can someone please go thru the GuestbookMapper.php line by line so as to explain what is going on? i m not a computer science major and would like a better explanation. also, any other resources that will explain this better would be great. thank you.
I had the same "Fatal error: Class 'Application_Model_Guestbook' not found in... error. The reason for this was an old ZendFramework verion delivered with xampp under PEAR/Zend. I just removed the directory to solve this.
Please help!
I am struggling with this error:
An Error Has Occurred
Action 'configure' is not a valid action.
I do not have any clue. I have successfully used the command mentioned in previous chapters.
I am using this and getting the above error:
>zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH '/../data/db/guestbook.db'" production
Please help!
I am struggling with this error:
An Error Has Occurred
Action 'configure' is not a valid action.
I do not have any clue. I have successfully used the command mentioned in previous chapters.
I am using this and getting the above error:
>zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH '/../data/db/guestbook.db'" production
@Nigel King comment has saved me. I have changed the Class name in Guestbook.php from Model_DbTable_Guestbook to Application_Model_DbTable_Guestbook and it is working.
But what is the real solution? I think it is a bug in code generation.

(Even this comment form is very unfriendly. )
I have written an article based on the too friendly doc. I cannot mention the link as that will be flagged. Search satya61229 and you may get my blog: satya-weblog dot com. For XAMPP user, it should be very very helpful.
I am configuring Zend for first time and getting following error .... can any body help


Catchable fatal error: Argument 1 passed to Zend_Db_Select::__construct() must be an instance of Zend_Db_Adapter_Abstract, null given, called in G:\Program Files (x86)\Zend\ZendServer\share\ZendFramework\library\Zend\Db\Table\Select.php on line 76 and defined in G:\Program Files (x86)\Zend\ZendServer\share\ZendFramework\library\Zend\Db\Select.php on line 163



Thanks in advance for proving solution
I am configuring Zend for first time and getting following error .... can any body help


Catchable fatal error: Argument 1 passed to Zend_Db_Select::__construct() must be an instance of Zend_Db_Adapter_Abstract, null given, called in G:\Program Files (x86)\Zend\ZendServer\share\ZendFramework\library\Zend\Db\Table\Select.php on line 76 and defined in G:\Program Files (x86)\Zend\ZendServer\share\ZendFramework\library\Zend\Db\Select.php on line 163



Thanks in advance for proving solution
I recive:
"Action 'configure' is not a valid action"
for:
"zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH '/../data/db/guestbook.db'" -s production",
and renaming class not help( What a problem can be?
Please remove the # from the beginning of lines... it makes the code hard to copy+paste.
If you see the header line followed by Application error

Make sure in your mysql configuration file(my.cnf)
skip-networking is commented.

comment out the line at my.cnf then restart mysql.

VEry very important. I was pulling my hair out for last two weeks. now got the Solution. It feels like I'm the king of the world :D
I have the same error as Amardeep :
Catchable fatal error: Argument 1 passed to Zend_Db_Select::__construct() must be an instance of Zend_Db_Adapter_Abstract, null given, called in D:\xampp\php\PEAR\Zend\Db\Table\Select.php on line 76 and defined in D:\xampp\php\PEAR\Zend\Db\Select.php on line 163
I can't figure out what the error in the code could be. :-(
Anyone has already faced and fixed that one ?
thanks
My only problem here was that in the previous tutorial I set up my application without setting the APPLICATION_ENV variable to Development... and therefore I 'm actually in production... And the database was not created!
Example should have a "red alert" for not being able to connect to the database
My only problem here was that in the previous tutorial I set up my application without setting the APPLICATION_ENV variable to Development... and therefore I 'm actually in production... And the database was not created!
Example should have a "red alert" for not being able to connect to the database

PS:
The captcha system is crap...
1)it is human unreadable;
2) It always tell me that the message was posted...
3) I really must be blind... (just to say I've been trying lots of times now)
4) This is impossible... I got it right this time
5) #/¤/(Q/&¤=
My only problem here was that in the previous tutorial I set up my application without setting the APPLICATION_ENV variable to Development... and therefore I 'm actually in production... And the database was not created!
Example should have a "red alert" for not being able to connect to the database

PS:
The captcha system is crap...
1)it is human unreadable;
2) It always tell me that the message was posted...
3) I really must be blind... (just to say I've been trying lots of times now)
4) This is impossible... I got it right this time
My only problem here was that in the previous tutorial I set up my application without setting the APPLICATION_ENV variable to Development... and therefore I 'm actually in production... And the database was not created!
Example should have a "red alert" for not being able to connect to the database

PS:
The captcha system is crap...
1)it is human unreadable;
2) It always tell me that the message was posted...
3) I really must be blind... (just to say I've been trying lots of times now)
4) This is impossible... I got it right this time
My only problem here was that in the previous tutorial I set up my application without setting the APPLICATION_ENV variable to Development... and therefore I 'm actually in production... And the database was not created!
Example should have a "red alert" for not being able to connect to the database

PS:
The captcha system is crap...
1)it is human unreadable;
2) It always tell me that the message was posted...
3) I really must be blind... (just to say I've been trying lots of times now)
4) This is impossible... I got it right this time
I have been followed the complete steps as given in this quickstart toturial. Once i complete this step and tried to access the guestbook page, i am getting 404 file not found error.

I am using Windows XP and iis 5.1

Please help me to cross out this hurdle.
This tutorial makes the simplest things sound complicated and misses out important information. Even after following the tutorial step by step, something always does not work as it should and I have to read the comments or do internet searches to sort out the problem.

In my view, this tutorial makes Zend a frustrating learning experience.
This tutorial help me a lot, informations are very usefull, My ZF application based on this architecture works well :)
I have made some improvements on the code structure, particularly on Map classes. Here is the result:

All Mapper classes extends from an abstract class, which refactor majority of the code. Some static functions make instanciation of mapper optional.

Be careful: this code works for PHP >= 5.3, because of static attribute.

------------------------------------------------------------------------------------------
abstract class Model_Mapper_Abstract
{
protected static $_dbTableName;
protected $_dbTable;


public function setDbTable($dbTable) {
if (is_string ( $dbTable )) {
$dbTable = new $dbTable ( );
}
if (! $dbTable instanceof Zend_Db_Table_Abstract) {
throw new Exception ( 'Invalid table data gateway provided' );
}
$this->_dbTable = $dbTable;
return $this;
}

/**
* @return Zend_Db_Table_Abstract
*/
public function getDbTable() {
if (null === $this->_dbTable) {
$this->setDbTable ( 'Model_DbTable_' . ucfirst(static::$_dbTableName) );
}
return $this->_dbTable;
}

public function find($id) {
$result = $this->getDbTable ()->find ( $id );
if (0 == count ( $result )) {
return null;
}
$row = $result->current ();
$model_className = "Model_" . ucfirst(static::$_dbTableName);
$customer = new $model_className ( $row->toArray () );
return $customer;
}

public function getAll() {
return ($this->fetchResults($this->getDbTable ()->fetchAll ()));
}

protected function fetchResults($resultSet) {
$entries = array ();
$model_className = "Model_" . ucfirst(static::$_dbTableName);
foreach ( $resultSet as $row ) {
$entries [] = new $model_className ( $row );
}
return $entries;
}

public static function getAllResults() {
$dbTable_className = 'Model_DbTable_' . ucfirst(static::$_dbTableName);
$model_className = "Model_" . ucfirst(static::$_dbTableName);
$dbTable = new $dbTable_className ( );
$resultSet = $dbTable->fetchAll ();
$entries = array ();
foreach ( $resultSet as $row ) {
$entries [] = new $model_className ( $row->toArray() );
}
return $entries;
}

public static function findById($id) {

$dbTable_className = 'Model_DbTable_' . ucfirst(static::$_dbTableName);
$dbTable = new $dbTable_className ( );
$result = $dbTable->find ( $id );
if (0 == count ( $result )) {
return null;
}
$row = $result->current ();
$model_className = "Model_" . ucfirst(static::$_dbTableName);
$object = new $model_className ( $row->toArray () );
return $object;
}
}
------------------------------------------------------------------------------------------



Having said that, here is the structure of a concrete Mapper. The save function is still here, because of the specificity for each class. This method can be implemented in abstract class thanks to toArray() method in the model (as Youssef Eldakar said), but I don't recommand it:
- responsibility of dababase schema must remains in Zend_DbTable and Mapper classes
- responsibility of Model classes must remains in Model_* and Mapper classes.
------------------------------------------------------------------------------------------
class Model_Map_GuestBook extends Model_Mapper_Abstract {
protected static $_dbTableName = "guestBook";

public function save(Model_Guestbook $guestbook)
{
$data = array(
'email' => $guestbook->getEmail(),
'comment' => $guestbook->getComment(),
'created' => date('Y-m-d H:i:s'),
);

if (null === ($id = $guestbook->getId())) {
unset($data['id']);
$this->getDbTable()->insert($data);
} else {
$this->getDbTable()->update($data, array('id = ?' => $id));
}
}
}
------------------------------------------------------------------------------------------


Last Tip: here is some functions I suggest to integrate in mapper during development phase. There is no value-added code here, but this permit a full completion (Type Hinting) support in environments like PHP Eclipse, Zend Studio...
------------------------------------------------------------------------------------------
/**
* @return Model_GuestBook
**/
public function find($id) {
return parent::find($id);
}

/**
* @return Model_GuestBook
**/
public static function findById($id) {
return parent::findById($id);
}

/**
* @return Model_DbTable_GuestBook
**/
public function getDbTable() {
return parent::getDbTable();
}
------------------------------------------------------------------------------------------

Hope this helps :)

Regards,
Damien THIESSON

Anyone who wants to enable mysql for this demo also has to make sure that his/her php5 is configured to use mysql with the PDO adapter, IE:

./configure --with-apxs2=/usr/local/apache/bin/apxs --with-mysql --enable-pdo --with-pdo-mysql=shared

After that I had to add the pdo-mysql.so extension to php.ini, and it worked.

-Sean

Why does the find method in the mapper class take an instance of the guestbook model as a second parameter?
Maybe I am mission something but shouldn't the find method instantiate the model as the fetchAll method does in it's foreach loop?
Or should I create an instance of the guestbook model before calling the find so that I can pass the second parameter.

*** application/models/GuestbookMapper.php    (web)
--- application/models/GuestbookMapper.php    (maybe)
***************
*** 42,44 ****
   
!     public function find($id, Application_Model_Guestbook $guestbook)
      {
--- 42,44 ----
   
!     public function find($id)
      {
***************
*** 49,50 ****
--- 49,51 ----
          $row = $result->current();
+         $guestbook = new Application_Model_Guestbook();
          $guestbook->setId($row->id)
I wish this manual would explain the creation and application of a db adapter in pure PHP, without the % zf magic. I am missing the connection to the database in the model.
Hm, also die Beschreibung (DE) hat unmengen von schaibfeelar. Es ist nicht beim ersten mal lesen zu erkennen welche Schritte gelesen und welche auszuführen sind. Die Codeansicht liefert keine Informationen ob einleitende <?php und abschliesende ?> benötigt werden. Pfadangaben mangelhaft (wer so beschreibt frisst bestimmt auch kleine Kinder), von wo aus soll was getan werden (zb c:\Zend\...\...\> zf mach was ich sage)?, Befehls unterscheidungen je OS nicht vollständig angegeben.

Comments: Sagt mal wollt Ihr hier überhaupt hilfe erhalten, bitte immer OS und Datenbank Typ angeben, eine Baumansicht der Verzeichnisse würde auch helfen.

Meine Schwierigkeiten bisher: (Vista, MySql | SQLITE)
Erstes war zu erkennen das man den (database excel sheet) nicht wie angegeben bei Windows verwenden kann sondern mittels c:\Zend\Apache2\meineTest\> zf create db-table Guestbook guestbook.
Tja und zwischendurch habe ich bemerkt das die NaviMenüpunk nach http://localhost/test/public/guestbook weist.

Fazit: Diese Beschreibung sollte man ignorieren da auch die Comments grösstenteils unbrauchbar sind. Es stellt sich jetzt für mich die Frage doch weiter ein eigenes Framework zu nutzen und weiter meine Lebenszeit mit eigenem KauderwelchFramework zu arbeiten.

Im übrigen gibt es gute beschreibungen wie man gute beschreibungen anfertigt. Es müsste ein Gesetz dagegen geben solche Schriftstücke auf die Menschheit loszulassen.




I get "Warning: Invalid argument supplied for foreach() " on my guestbook page, everything else works fine.

To get mysql working I had to add these lines to my php.ini:
extension=pdo.so
extension=pdo_mysql.so

and these lines to my application.ini under [production]

resources.db.adapter="PDO_MYSQL"
resources.db.params.host="localhost"
resources.db.params.username="bobandst"
resources.db.params.password="p1ssw2rd"
resources.db.params.dbname="bobandst_Main"


I also had to add this line to my .htaccess file to get the development environment:
SetEnv APPLICATION_ENV development

My application still seems to have issues connecting to the database, are there more config lines that I am missing?
This tutorial doesn't work at all. I'm having Fatal error: Class 'Application_Model_GuestbookMapper' any any tips from comments don't help..
i ma new to zend i know that construct use setOptions but $options is null can anyone explain me how does it work __construct and __get and __set


public function setOptions(array $options)

{
$methods = get_class_methods($this);
foreach ($options as $key => $value) {

$method = 'set' . ucfirst($key);

if (in_array($method, $methods)) {
$this->$method($value);
}
}
return $this;
}
This example is wrong working with DB.

If you use DB then class constructor mus have
class Application_Model_Guestbook
{
protected $_comment;
protected $_created;
protected $_email;
protected $_id;

public function __construct(array $options = null)
{
parent::__construct($options); // This line must be to set DB adapter
if (is_array($options)) {
$this->setOptions($options);
}
}
}
I'm still unsure about whether my domain model should be returning Zend_Db_Table_Rowsets or arrays of custom objects. I've used Zend_Paginator with the DbTableSelect adapter and found it very useful. How would I handle pagination when my dataMappers are not passing back Zend_Db_Table_Rowsets but rather arrays of my model objects? Would I use Zend_Paginator in the dbTable resource files, allow the mapper to pull out the rows and create model objects from them and then pass the paginator object back some other way?
I have been followed the complete steps as given in this quickstart toturial. Once i complete this step and tried to access the guestbook page, i am getting 404 file not found error.

I am using Windows 7 Zend Server CE

Thanks!!!
I don't understand this point in the Mapper code:

$data = array(
'email' => $guestbook->getEmail(),
'comment' => $guestbook->getComment(),
'created' => date('Y-m-d H:i:s'),
//--> maybe here we should be adding 'id'=> $guestbook->getId();
);

if (null === ($id = $guestbook->getId())) {
unset($data['id']);
$this->getDbTable()->insert($data);
} else {
$this->getDbTable()->update($data, array('id = ?' => $id));
}


Why are we 'unset'-ing a variable that was never set? Should we add $data['id'] first? Are we assuming Id is an auto_increment field? That's why we are not inserting it to the table? What am I missing here?
@Marie-Helene, the reason to not use the Zend_Db_Table_Row directly is that the author is trying to demonstrate a method for decoupling DOMAIN objects from persistent database records. In MANY scenarios, your point makes sense, but there are many places where it falls apart and it is better to just build the right plumbing initially to save time later.

@Youssef -- You seem to be exposed to this as well by trying to reflect on the incoming array in order to derive the table's column names. You should consider always implementing a mapper between domain objects and the storage of the data.

Ok, I wrote reams of text and then realized that I should Google Data Mapper Pattern to see if anybody said it more succinctly so I deleted mine and I direct you to Martin Fowler's description... (the point that I had written reams about was collection of objects in objects. This is something that can be handled by a mapper -- although if you're going to be doing this extensively, it would be worth looking into a full-blow ORM solution like Hibernate, or Doctrine/Outlet)

http://martinfowler.com/eaaCatalog/dataMapper.html
Magnus Olsson on: 2011-02-07 07:30:40:
Why does the find() method in the mapper class take an instance of the guestbook model as a second parameter?

This is something that I don't understand either. Can someone please clarify this for us?
matttrach on: 2011-04-18 18:22:02:
I don't understand this point in the Mapper code:
public function save(Application_Model_Guestbook $guestbook)
{
    $data = array(
        'email'   => $guestbook->getEmail(),
        'comment' => $guestbook->getComment(),
        'created' => date('Y-m-d H:i:s'),
    );

     if (null === ($id = $guestbook->getId())) {
        unset($data['id']); // <<< It is about this code. What's it doing here?
        $this->getDbTable()->insert($data);
    } else {
        $this->getDbTable()->update($data, array('id = ?' => $id));
    }
}

Why are we 'unset'-ing a variable that was never set?

I wonder how this code ended up in here. Right now it is clearly unnecessary, so I will not implement this line of code in my applications.
But hey, someone willing to relief us with the thruth would be welcome, 'cause this code is bugging me. LOL
It has been a rough task to learn this framework. I am still stuck at quick start.

I am using PDO_MYSQL as my adapter. I have followed the tutorial to the letters.

At a point, it says to create application/models/GuestbookMapper.php and put the following code

class Application_Model_GuestbookMapper
{
public function save($model);
public function find($id, $model);
public function fetchAll();
}

Then it say to run this command

zf create model GuestbookMapper

The tutorials claims to insert additional methods. But in my case, it emptied the my GuestbookMapper class with this

class Application_Model_GuestbookMapper
{

}

Same goes with another command zf create model Guestbook. It empties the scripts, with just plain class defination.

Please help me !
For all of you cannot reach the guestbook page or any page other then the front page. You remember to add:

<Directory "C:\Zend\Apache2/htdocs/Quickstart/public">
DirectoryIndex index.php
AllowOverride All
Order allow,deny
Allow from all
</Directory>

I didn't pay attention - I only added:

<VirtualHost *:80>
ServerName hello.localhost
DocumentRoot "C:\Zend\Apache2/htdocs/newapp/HelloWorld/public"
#DocumentRoot "C:\Zend\Apache2/htdocs/Quickstart/public"

SetEnv APPLICATION_ENV development

</VirtualHost>

I hope this can help others with the same issue ; )
Hi,

For those who r using Abyss web server, dun forget to set the URL rewriting.. if not you will get error 404.

http://www.aprelium.com/abyssws/articles/urlrewriting-modrewrite-conversion.html
The "unset($data['id'])" - doesn't make sense. And it should be removed. Right ?

Why isn't ?
why the auto loading not initiate by its own?
I USE in WIN 7
zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH '/../data/db/guestbook.db'" production
I guess this solution is more easy and implement very fast.

$resultSet = $this->getDbTable()->fetchAll();
$entries = array();
foreach ($resultSet as $row)
{
$entry = new Application_Model_Guestbook();
foreach ($row as $key => $value)
{
$method = 'set'.ucfirst($key);
$entry->$method($value);
}
$entries[] = $entry;
}
return $entries;

Thanks the community for the best framework of the world!

JCROOT
when i use the ZF tool to create a model ... it does so inside /applications/models/DbTable/ModelName.php ... is the model in this tutorial analogous to that ZF created model? supplemental? i ask because i have noticed that the details tend to shift over each iteration of the ZF framework. the path to the Zend includes being one of those details that has shifter since 1.7 ... to 1.11 (current). if this tutorial is 'current' ... why not use the ZF tool?
is this tutorial even relevant to someone using MySQL server?
why use an MVC framework to write to what is basically a flat file? sql lite ... when does anyone ever use that db?
los comandos zf configure db_adapter tal cual como estan escritos en el tutorial, utlizando netbeans 6.9.1 "NO FUNCIONAN".
La unica manera de hacerlos andar fue asi:

zf configure db-adapter "adapter=Mysql&dbname=APPLICATION_PATH '/../data/db/guestbook.db' " -s production

cambiando para cada section el archivo y el valor de -s.

Espero le sirva a alguien
fdgdf
if your documentroot doesn't point directly to the public folder you'll need to set the rewritebase

ex: 127.0.0.1/asdf/jkl/public/

in .htaccess add

RewriteBase /asdf/jkl/public/

you'll get a 404 w/o
This is a really poor tutorial. Installed Zend Server on a Ubuntu VM and it broke my other Apache/PHP install. Finally got it sorted out and back to a running state and installed a standalone Zend Framework into my existing Apache/PHP stack.

The tutorial then:
- fails to tell you exactly where to put files (like the database and SQL/loader scripts)
- contains incomplete code (people have to insert the <?php ?> tags themselves)
- doesn't explain enough as it goes along - I feel like I'm learning how to build a very simple app without the tutorial explaining WHY I'm doing certain things, like creating the Application_Model_GuestbookMapper class, or creating a huge long script to set up my database

And now...on top of all that...I'm stuck because the load.sqlite.php script won't define the APPLICATION_PATH and so the script can't find the application.ini

Do I really want to learn a framework for developing apps when the developers of the framework can't even write a decent tutorial?

1/2 hour? It's taken me all day to get this far and I'm giving up.
Can anyone provide me a step by step tutorial of zend Framework.
it started from basic knowledge such as folder structure or cover all the area
of web application like database connectivity ,query to database.

please reply as soon as possible It is argent.
So there's a lot of stuff going around here that i don't really get. Most of the code provided above is quite easy to understand if you've worked with the framework a little bit and thread throughoutly.

But there's a few lines i don't get:
public function find($id, Application_Model_Guestbook $guestbook)
    {
        $result = $this->getDbTable()->find($id);
        if (0 == count($result)) {
            return;
        }
        $row = $result->current();
        $guestbook->setId($row->id)
                  ->setEmail($row->email)
                  ->setComment($row->comment)
                  ->setCreated($row->created);
    }

1) How is one supposed to make use of that function?
So i assume i have to be like
$table = new Application_Model_GuestbookMapper();
$row = new Application_Model_Guestbook();
$row_that_i_want = $table->find(42, $row);

Even if that were correct, the code would still not du anything? It does not give anything back!? There is no return, so that assignment has no use...


2) Then what i don't understand either with the three-layered abstraction is,
We have a tableMapper-class
We have a tableRowset-class
We have a tableRow-class

The only thing that extends something from the framewok is the tableMapper
Shouldn't the tableRowset and tableRow extend the specified Zend-Classes, too?

Because:
How am i supposed to built relationships between tables with the code provided above?
I can assign the relationships inside the tableMapper class, but how do i access them?

I would want to be like:
$table = new tableMapper();
$row = $table->find(1); // eventually $table->find(1)->current();
Lets say i got an Author with this, from this author i want to retrieve all books
$row->getBooks();

The getBooks(); funktion in the rowclass would call something like findDependentRowset();
But the rowClass doesn't know that functiuon, als there is no connection.


Now i have built relationships of tables in a previous project where i simply used a rowsetClass and a rowClass - with the tableMapper on top i don't know how i would be able to do this at all. it's just a little bit weird.

As many people have problems with understanding this quickstart, i think the quality should be checked again
And please just use mysql or a sql server - no one wants to "copy and see how it works" with a sqLite file.. ;)

I found the quick start document make me more confused.
For those of you who feel you have followed the guidelines perfectly, and has configured the rewrite rules and enabled these in apache, but still get a 404.
Try looking at the vhost configuration. If AllowOverride is not set to All, it will not work!
I must say one thing.. zend is good but this article is very poorly written.

I agree with most of the people here who are having issues with Mysql as there is nothing specific given for that.

I request you guys to please post or edit this article and mention , how to configure the quickstart project with mysql.

I will be waiting

Noddy
I suggest to all, do not follow this tutorial. Find better with uncle google help.
bad tutorial
Really bad tutorial...... Here are some links which may be useful,

http://www.phpeveryday.com/articles/Zend-Framework-Basic-Tutorial-P840.html
http://www.survivethedeepend.com/
Learning ZF has been frustrating as hell. Most ZF tutorials I have read so far are just like this one: twisted, incomplete and full of errors.

I appreciate the good intentions of the author, but the results are very frustrating for programmers trying to learn this framework.

Why not use MySQL?
Why create a twisted script to create the database?
Why do I have to guess the directories I have to use?
Why make assumptions?

Please, keep it simple, and be thorough in the explanation. I am not giving up on ZF, but I am really disappointed in the Zend communitiy efforts to educate the new comers.
Why is this tutorial for SQLITE as long as the ZendServer CE is shiped with mysql?
In adition you cannot create any Database in this MySQL-Server.
How can one test their application if one have no right to create the database?

But nice to read, that I'm not the only frustrated one.
I fully agree with Manolo. I've been stuck at the following error "Fatal error: Class 'Application_Model_GuestbookMapper' not found in C:\xampp\htdocs\blog\application\controllers\GuestbookController.php on line 13".

I find that there should be small steps instead of making a high level tutorial especially while talking about a quick tutorial for beginners.
Hi,
I did this tutorial and everything worked after setting up my httpd.conf und my paths for php and zf tool. But if I send up my form to write into my database there was a problem and I got error "page not found".Look at code below:

if ($this->getRequest()->isPost())
{
if ($form->isValid($request->getPost()))
{
$model = new Application_Model_Guestbook($form->getValues());
// line that doesn't work is here:
$model->save();
return $this->_helper->redirector('index');
}
}

I solved it this way:
if ($this->getRequest()->isPost())
{
if ($form->isValid($request->getPost()))
{
$model = new Application_Model_Guestbook($form->getValues());
// my solution
$guestbook = new Application_Model_GuestbookMapper();
$guestbook->save($model);
// end of my solution
return $this->_helper->redirector('index');
}
}

I'm not the real ZF-Crack. I see, the Guestbook mapper is initiated in the IndexAction(). Now I'm not sure how PHP handles this. Does PHP create this instance of class only for the IndexAction() or does it create this instance global? In second case it must work without my solution.... Is there anyone with a better solution or the same problem? (And sorry for my bad english.. :) )
Sorry, my last post belongs to GuestbookController.php :)
To practice on mysql databse please use add below lines to [production] section in application.ini

resources.db.adapter = "pdo_mysql"
resources.db.params.host = "localhost"
resources.db.params.username = "root"
resources.db.params.password = ""
resources.db.params.dbname = "my_database_name"
resources.db.isDefaultTableAdapter = true

and execute below queries in your mysql database



CREATE TABLE guestbook (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
email VARCHAR(32) NOT NULL DEFAULT 'noemail@test.com',
comment TEXT NULL,
created DATETIME NOT NULL
);

CREATE INDEX id ON guestbook (id);

INSERT INTO guestbook (email, comment, created) VALUES
('ralph.schindler@zend.com',
'Hello! Hope you enjoy this sample zf application!',
NOW());

INSERT INTO guestbook (email, comment, created) VALUES
('foo@bar.com',
'Baz baz baz, baz baz Baz baz baz - baz baz baz.',
NOW());

Keep other classes same as mentioned above.
This section of tutorial has some bugs.

0. Please remember to surround the load.sqlite.php content with <?php and ?>

1. In case you see "The sqlite driver is not currently install"
For basic LAMP installation you might need to do
>sudo apt-get install php5-sqlite
To install sqlite driver.

2. In case you see "SQLSTATE[HY000] [14] unable to open database file
Remember to move data and scripts in the correct folder

Put "scripts" and "data" folders in the same folder of
"application data docs library public scripts tests"

where there are:
scripts/load.sqlite.php
data/db/
Congrats Zend Team for messing up with your tutorial.
I don't know if it's only me but i find setting up Zend to work is a tedious task. instead of making the development faster, just slows it down plus this messed up tutorial. Nice!
If you're getting a 404 or 403 on the guestbook page you might want to check that:
- you set the absolute path to your installation on both the DocumentRoot and Directory directive in your httpd.conf.
- you have Options +FollowSymLinks in either your .htaccess or your httpd.conf VirtualHost > Directory directive.
hth
If you are using xampp and getting 404 errrors, you need to set Apache's DocumentRoot as your 'Public' folder "C:\...\xampp_dir\...\projectname\Public".

This is done in the Apache configuration file: "C:\...\xampp_dir\apache\conf\httpd.conf"
JOB OFFER TO ALL INTERESTED APPLICANTS .
I am Mrs Antonia Benson , I work in Sunshine Dairy Foods Company here in Canada ,

we need workers from all parts of the world to join the company , whether skill or

unskilled they are all qualified to join the company .
You can also invite any of your friends and relatives to join us either the branch

in Canada or United kingdom.
All approved applicants are to be granted free air plane ticket and free

accommodation , applicants are only responsible for work permit visa requirements

with the Canada Immigration Bureau here upon received of employment form.
Contact us through this email:sunshineemploymentinfo@inmail.sk , or

(sun.shinecompany@yahoo.ca)

Your best Cooperation is highly appreciated .
Mrs Antonia Benson,
Employment Consultant Officer ,
Human Resources Department .
150 - 6TH AVENUE SW CALGARY
ALBERTA T2P 3Y7,CANADA.
Piotr ;) I can tell you that with a little bit more patience and effort, you will get it running. Check your errors and you'll be fine.
MICROSOFT is making very good tutorials for asp.net TRY LEARN FROM THEM!!!

Ouch, do not forget to realize, this whole project is open source and free.

Thanks for this tutorial guys!! Loving ZF!
Hallo

Ein kleiner Schönheitsfehler beim INSERT von data.sqlite.sql


INSERT INTO guestbook (email, comment, created) VALUES
    ('ralph.schindler@zend.com',
    'Hallo! Hoffentlich geniesst Ihr dieses Beispiel einer ZF Anwendung!
    DATETIME('NOW'));


Es fehlt das ' und das komma danach!


'Hallo! Hoffentlich geniesst Ihr dieses Beispiel einer ZF Anwendung!',

gruß
Is it really necessary to show what has changed and then the whole file again? Or is it just done to make this tutorial look bigger than it is?
A Zend tutorial that's not terrible:

http://www.phpeveryday.com/articles/Zend-Framework-Basic-Tutorial-P840.html
I've just run through the quickstart using a fresh copy of ZendFramework-1.11.9 (Mac OSX 10.6.8) and at this point I haven't had any major problems at all yet.

I skipped the 'zf configure db-adapter' portion and simply added the mysql details in the application.ini as mentioned above:

resources.db.adapter = "PDO_MYSQL"
resources.db.params.host = "localhost"
resources.db.params.username = "mysqlusername"
resources.db.params.password = "mysqlpassword"
resources.db.params.dbname = "dbname"


I appreciate there are a lot of comments (and good info) above and maybe as a result the tutorial may have been amended over time to where it is now.

New users running through this for the first time might simply give up after reading all the comments, however, it's really not that bad :)



There is an answer at the bottom of this message.

Scroll down if you're in a hurry.




--------------- Problem --------------------

Running zf configure db-adapter on windows with the arguments given in this tutorial, does not work.

There are a lot of comments about not being able to run the commands given to configure the db-adapter on windows machines.

The commands given are formatted for linux and aren't easily converted.




--------------- Issue -----------------

Command Given:

% zf configure db-adapter \
> 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook.db"' \
> production

The trick is that the argument:

'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook.db"'

contains spaces, double quotes, and the & symbol.




--------------- Working out the solution ------------------

spaces delimit arguments. Resolve by wrapping in double quotes.
& is used when writing multiple commands on a single line. as in
dir&tree
will give you a directory listing followed by a tree. Resolve by escaping the & with ^ when the & lies outside of a literal string.

I'm assuming the intention of wrapping the entire argument in single quotes on linux is to pass it as a literal string. On windows you pass an argument as a literal string by wrapping it with double quotes. So first convert the single quotes to double quotes.

"adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook.db""

Then notice that the command won't work. This is because the argument contains double quotes and ends up being parsed as several arguments instead of one.

So step 2, find all the double quotes inside the argument and double them.

"adapter=PDO_SQLITE&dbname=APPLICATION_PATH ""/../data/db/guestbook.db"""

Now you might be thinking about escaping the &, don't. The & is interpreted literally, not as a control character or anything special. If the & or any other special character ends up outside of the literal string, then you need to escape them with ^.




--------------- Solution ---------------------------

PLEASE INCLUDE THIS ALTERNATE SET OF COMMANDS FOR WINDOWS USERS. :D

The whole thing ends up converting to this:

C:\path\to\project\root\> zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH ""/../data/db/guestbook.db""" production


C:\path\to\project\root\> zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH ""/../data/db/guestbook-testing.db""" testing


C:\path\to\project\root\> zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH ""/../data/db/guestbook-dev.db""" development

********** convert C:\path\to\project\root\ to the location of your project folder ( parent of application folder ) **********




--------------- Results ---------------

[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
appnamespace = "Application"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.frontController.params.displayExceptions = 0
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
resources.view[] =

resources.db.adapter = "PDO_SQLITE"
resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook.db"

[staging : production]

[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

resources.db.adapter = "PDO_SQLITE"
resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-testing.db"

[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
resources.frontController.params.displayExceptions = 1

resources.db.adapter = "PDO_SQLITE"
resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-dev.db"


********** Notice that **********

resources.db.adapter
and
resources.db.params.dbname

both have exactly the same values as given in the tutorial when using the commands given in my solution.



----- Side note --------

Could we run zf.php with the CLI and avoid a lot of confusion? Interactive mode is still broken on windows machines as far as I know, but I work around it with:

<?php
while (1) {
fputs(STDOUT, "\r\nPHP_MODE: ");
eval(trim(fgets(STDIN)));
}
?>

I save that to a file called interactive.phps and start it with:

C:\path\to\php.exe -f "C:\path\to\interactive.phps"

and php interprets everything I type. There's no error handling, so if you type anything wrong the window will close. When you're done type exit; and you'll leave PHP_MODE and be back to the shell you were in before.

If say. . . the environment variables could be set with a php file and this snippet had some sort of error handling then we could forget about a lot of differences between linux and windows command line syntax. . . maybe. . .


... or maybe a web interface for common . . . I don't know what I'm getting into. . ..






--------------- Quick Solution For the Impatient ---------------------------

PLEASE INCLUDE THIS ALTERNATE SET OF COMMANDS FOR WINDOWS USERS. :D

The whole thing ends up converting to this:

C:\path\to\project\root\> zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH ""/../data/db/guestbook.db""" production


C:\path\to\project\root\> zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH ""/../data/db/guestbook-testing.db""" testing


C:\path\to\project\root\> zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH ""/../data/db/guestbook-dev.db""" development

********** convert C:\path\to\project\root\ to the location of your project folder ( parent of application folder ) **********
In the generated index.php file contained in the quickstart/public folder for this project it defines:

defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

APPLICATION_PATH seems to be a sibling folder of the folder containing index.php, specifically it would resolve to quickstart/application/ unless intentionally changed.

So APPLICATION_PATH = quickstart/application

then in application.ini we set the databases for test dev and production to all go into one folder located at:

resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-dev.db"

APPLICATION_PATH/../data/db/guestbook-dev.db

quickstart/application/../data/db/guestbook-dev.db

quickstart/data/db/guestbook-dev.db

This is also the file structure in the zip file of the completed tutorial. So it is safe to assume that the folders "data" and "application" are siblings whose parent is the folder "quickstart".



Please edit this section of the tutorial:

---- Quote ------

Note that the database(s) will be stored in data/db/. Create those directories, and make them world-writeable. On unix-like systems, you can do that as follows:

% mkdir -p data/db; chmod -R a+rwX data

On Windows, you will need to create the directories in Explorer and set the permissions to allow anyone to write to the directory.

At this point we have a connection to a database; in our case, its a connection to a Sqlite database located inside our application/data/ directory. So, let's design a simple table that will hold our guestbook entries.

---- End Quote -----

Specifically, the directories confuse me and there are other comments saying the same thing. If you could change the reference to "data/db/" into "quickstart/data/db/" then it would be very clear where the data directory belongs. Also, change the reference to "application/data/". I didn't see any instruction to create this folder and it was also not present in the completed project.


quickstart was the name of the initial folder we made on the second page of this tutorial. It serves as an effective point of reference when we're going through this tutorial where we're not familiar with the file structure or methods or basically anything. I don't even remember what I was reading because I've wasted so much time reading typos and converting linux command syntax into something that works on windows so I could use the batch file referenced in these very instructions.


I AM NOT A HAPPY DUCK. :(


Is the Zend Framework really worth all this effort?


I will be back to try doing all this by hand again. Don't delete my comments. I'll need them for next time. . .
Anyone that receives the 500 Error or a "File not found" error when attempting to access localhost/public/guestbook needs to ensure they added the <Virtualhost> settings to their httpd.conf file.
Also, to everyone complaining about this tutorial not being perfect, don't use it. In programming and scripting you are going to run across problems and issues which you need to be able to solve on your own.

The writer for this had alot of content to cover, and cannot compensate for everything that everyone may or may not already know. If you're even attempting to learn a framework then you should already have some common coding sense and problem solving skills or else you failed before you even came here.
@matttrach: There is mistake in view/scripts/guestbook/index.phtml. There should be:

Guestbook Entries: <br />

<dl>
<?php foreach ($this->entires as $entry): ?>
<dt><?php echo $this->escape($entry->email) ?></dt>
<dd><?php echo $this->escape($entry->comment) ?></dd>
<?php endforeach ?>
</dl>

but ther is:
Guestbook Entries: <br />

<dl>
<?php foreach ($this->entries as $entry): ?>
<dt><?php echo $this->escape($entry->email) ?></dt>
<dd><?php echo $this->escape($entry->comment) ?></dd>
<?php endforeach ?>
</dl>

Best regards

Krzysiek

Ive just added the following lines to application.ini:
resources.db.adapter = "PDO_MYSQL"
resources.db.params.host = "localhost"
resources.db.params.username = "username"
resources.db.params.password = "pass"
resources.db.params.dbname = "dbname"
resources.db.isDefaultTableAdapter = true

Try just modifying localhost to 127.0.0.1 like the following:

resources.db.adapter = "PDO_MYSQL"
resources.db.params.host = "127.0.0.1"
resources.db.params.username = "username"
resources.db.params.password = "pass"
resources.db.params.dbname = "dbname"
resources.db.isDefaultTableAdapter = true

This way worked for me.
I can't believe that there isn't a complete example using MySQL!!! Following this SQLITE we're getting "lost in the sauce"!
Wow, this can be quick tricky in the corners, but that's a brilliant framework so it can't be too easy.

In my case I am using a mac with Zend Studio 8 and Zend Server 5.5. This quickstart is the zend framework example in Zend studio and almost everything is already written. but I wanted to get the php script to run and got stuck a bit trying to get this include_path to work.

At the end, I changed the APPLICATION_PATH and it works :

defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
set_include_path(implode(PATH_SEPARATOR, array(
APPLICATION_PATH . '.:/usr/local/zend/share/ZendFramework/library',
get_include_path(),
)));

good luck guys ;)
This tutorial sucks.
please streamline it.
thank you.
I follow these steps but to access the guestbook controller the browser displays 'not found'

What's problem?
In my Models I have a function:

public function getOptions(array $exceptions = array())
{
$data = array();
foreach ($this->options as $key => $value) {
$data[$key] = $this->__get($key);
}
return array_diff_key($data, array_flip($exceptions));
}

which allows me to get all of the data with one call rather than individually grabbing all options to store in a data array during something like a save:

public function save(Application_Model_Guestbook $guestbook)
{
$data = array(
'email' => $guestbook->getEmail(),
'comment' => $guestbook->getComment(),
'submitted' => date('Y-m-d H:i:s'),
);

public function save(Application_Model_Guestbook $guestbook)
{
$data = $guestbook->getOptions(array('id'));
% php scripts/load.sqlite.php --withdata production!!!
This is the worst documentation i have ever saw,helpless , thinking of moving to symfony .
shit
I agree, this is shit
Sorry everyone... we are way to busy to even bother reading, let alone update this tutorial. Once we get our thumbs out of our you-know-whats, we might get around to fixing this.
Hello everyboy,

Please, someone can tell me from where came these 'set' and 'mapper' in application/models/Guestbook.php?

public function __set($name, $value) {

//This set I'm asking
$method = 'set' . $name;

//This mapper I'm asking
if (('mapper' == $name) || !method_exists($this, $method)) {

throw new Exception('Invalid guestbook property');
}
$this->$method($value);
}

Also I would like suggest to Zend's people who make the quick start to write comments in the main example code. Maybe it can help better newbies like me.

Thanks!
too much problem with CLI, i found this solution, it's quick and easy:
1. just copy the 3 files data.sqlite.sql, schema.sqlite.sql and load.sqlite.php in public than
2. excute it from the browser just li this
http://quickstart.local/load.sqlite.php?w
you should see

Writing Database Guestbook in (control-c to cancel): 5 4 3 2 1 Database Created

don't mess with CLI, you will waste your time just like I did.
Bye

p.s.
PHP Version 5.3.2-1ubuntu4.10
eclipse Helios (still problem using zend CE modules)

extreamly hard to learn this framework
really wasted hours an hours to learn how to connect to db only.
Still no success
Just a note. I had to add the line ...
<?php
... as the first line of the file load.sqlite.php and add as the last line of this file ...
?>

probably obvious to experience php programers ... but not :)
"Not Found
The requested URL /quickstart/guestbook was not found on this server."

this complete source code http://framework.zend.com/demos/ZendFrameworkQuickstart.zip doesn't work too.

This is the second part of this tutorial that simply doesn't work. Still getting error messages (or the ZF default index page if I put in .../public/index.php).

I think this "quickstart" tutorial is poorly written and not properly tested in the real world.

I'm not an inexperienced php programmer and I'm struggling to get this to work. Very poor Zend....
Hi,
the document is very good, however few questions and hints arise that I want to share with you all.
First of all, my programming idea is DOWIN - Do Only What Is Necessary. An illustration: there is a framework-builtin mechanism that you may use 'as is' or modify/interface for your own. Do you REALLY need interfacing this mechanism? YES? Then go on. NO? Then leave it as it is, please.
Zend framework is a BRILLIANT thing, it's a diamond among the MVC frameworks. Thanks to the hard work of many brilliant programmers, developers, analysts, managers, it contains anything a PHP MVC programmer needs.

As for the models described in the article, let's see what we want to achieve by making them. Separation of data logic and data storage mechanisms? Then we/you are right about making separate "mapper" classes for them. Also, separation of mappers from classes extending Zend_Db_Table is much safer than introducing our own functionalities to the class that contains thousands of lines of code; at least we don't risk breaking anything defined in the parent, abstract class. So a "has-a" solution is as great as can be: we just make a class for table defining the database details, pack it in a nice and tidy suitcase of getter/setter, and we find it a shelf inside our model. Great.

As for the model for data item: I really think it's unnecessary to create getter/setter methods for all data.
For the basic functionality, it's absolutely reduntant. So according to DOWIN, let's think whether we really-really
need some extra functionality for each field? Do we? Then let's create getters and/or setters for the fields
we need the functionality, leaving others alone. It's enough to create class properties corresponding to each field
and checking in __get()/__set() methods if they exist in the class. For getters/setters as getXXXX() and setXXXX()
we/you can use __call() magic as well.

I got this same error:

And now...on top of all that...I'm stuck because the load.sqlite.php script won't define the APPLICATION_PATH and so the script can't find the application.ini

It is because the script folder for load.sqlite.php, schema.sqlite.sql and data.sqlite.sql should be in the same folder as:

"application data docs library public scripts tests"
In indexAction() method of IndexController I have called the method of model which returns the list of employees(employeeList) from database.And then add this this employeeList to $view and then call $view->render('index.phtml') and index .phtml shows the employeeList.Now I want to start the execution from indexAction() method.But how to do this?In request parameter the controller will be Index and action will be index.So please help me in resolving this issue.What should be url as the request in browser??Thanks in advance..
a really awful tutorial, seriously.
Poor news - Syria's 'mutilation mystery' increases...
nginx users this is my conf for handling the rewrites


server {
        listen 80;
        server_name vac.local;
    access_log /srv/projects/php/vac.local.access.log;
    error_log /srv/projects/php/vac.local.error.log;

 
    root   /srv/projects/php/vac/public;

        location / {
                index index.php;
        }
 
        # serve static files directly
        location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt)$ {
            access_log        off;
            expires           30d;
        }

    location ~ \.htaccess {
        deny all;
    }

    if (!-e $request_filename) {
        rewrite ^.*$ /index.php last;
    }
 
        location ~ \.php$ {
                fastcgi_pass 127.0.0.1:9000;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME /srv/projects/php/vac/public$fastcgi_script_name;
                fastcgi_param PATH_INFO $fastcgi_script_name;
                include /etc/nginx/conf/fastcgi_params;
        }
}
=========== Best Practice for Mysql here ============
==Step 1: add adapter
zf configure db-adapter 'adapter=PDO_MYSQL&dbname=guestbookdb' production
zf configure db-adapter 'adapter=PDO_MYSQL&dbname=guestbookdb_test' testing
zf configure db-adapter 'adapter=PDO_MYSQL&dbname=guestbookdb_dev' development

==Step2: edit sql, create schema & data
1)
mkdir scripts
2)
vi scripts/schema.mysql.sql
DROP DATABASE IF EXISTS guestbookdb;
CREATE DATABASE guestbookdb;
USE guestbookdb;

DROP TABLE IF EXISTS guestbook;

SET @saved_cs_client = @@character_set_client;
SET character_set_client = 'utf8';
SET character_set_connection= 'utf8';
SET character_set_results='utf8';
CREATE TABLE guestbook (
id int NOT NULL AUTO_INCREMENT,
email varchar(32) NOT NULL DEFAULT 'noemail@test.com',
comment TEXT NULL,
created DATETIME NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE INDEX id ON guestbook(id);

3)
vi scripts/data.mysql.sql
USE guestbookdb;

INSERT INTO guestbook (email, comment) VALUES
('ralph.schindler@zend.com',
'Hello! Hope you enjoy this sample zf application!');
INSERT INTO guestbook (email, comment) VALUES
('foo@bar.com',
'Baz baz baz, baz baz Baz baz baz - baz baz baz.');

4) execute:
mysql -uroot -p < scripts/schema.mysql.sql
mysql -uroot -p < scripts/data.mysql.sql

==Step3: just as standard steps to create following
zf create db-table Guestbook guestbook
zf create model GuestbookMapper
zf create model Guestbook
zf create controller Guestbook
add following configs to application/configs/application.ini at each section

resources.db.params.host = "localhost"
resources.db.params.username = "root"
resources.db.params.password = ""


=========nginx config=========
server {
listen 8000;
server_name quickstart.local;

location / {
root /home/thes/www/app/quick2/public;
index index.php;

if (!-e $request_filename) {
rewrite ^.*$ /index.php last;
}
}

location ~ \.php$ {
root /home/thes/www/app/quick2/public;
fastcgi_connect_timeout 600;
fastcgi_read_timeout 600;
fastcgi_send_timeout 600;
fastcgi_buffer_size 4k;

fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /home/thes/www/app/quick2/public/$fastcgi_script_name;
fastcgi_param APPLICATION_ENV development;
#fastcgi_param include_path /home/thes/www/app/quickstart/library/Zend;
include fastcgi_params;
}

}


nohup /usr/local/bin/php-cgi -b localhost:9000 &
<b>Dear ' "zf configure db-adapter" ' users,</b>
for windows the right usage is as follows (you have to change the order of the quotation marks):

zf configure db-adapter "adapter=PDO_SQLITE&dbname=APPLICATION_PATH '/../data/db/guestbook-dev.db' " development

Best regards
<b>Axel Arnold Bangert</b>
Wolfstrasse 2
52134 Herzogenrath, 14.01.2012


Dear users,
in the above script data.sqllite is a syntax error at the end of line 8 (missing quotation mark and missing komma!

Best regards
Axel Arnold Bangert
Wolfstrasse 2
52134 Herzogenrath, 14.01.2012


INSERT INTO guestbook (email, comment, created) VALUES
('ralph.schindler@zend.com',
'Hallo! Hoffentlich geniesst Ihr dieses Beispiel einer ZF Anwendung',
DATETIME('NOW'));
I agree with the others. This tut is horrible and generally useless to ZF beginners. I'm trying to follow these general guidelines but with a MySQL database and it's not working. The Zend Framework team really needs to update this documentation to include a real-world MySQL example.
In it something is also to me it appears it truly is excellent idea. I agree with you.
Why don't use the follow code in order to avoid writing a lot of getter/setter method?


    public function __set($name, $value)
    {
        $method = 'set' . $name;
        if (('mapper' == $name) || !method_exists($this, $method)) {
            if(array_key_exists('_'.$name, get_object_vars($this))){
                $this->$name = $value;
                return $value;
            }
                       
            throw new Exception('Invalid entity property');
        }
        $this->$method($value);
    }
 
    public function __get($name)
    {
        $method = 'get' . $name;
        if (('mapper' == $name) || !method_exists($this, $method)) {
            if(array_key_exists($name, get_object_vars($this))){
                return $this->$name;
            }           
            
            throw new Exception('Invalid entity property');            
        }
        return $this->$method();
    }
 
    public function setOptions(array $options)
    {
        $methods = get_class_methods($this);
        foreach ($options as $key => $value) {
            echo $key;            
            $method = 'set' . ucfirst($key);            
            if (in_array($method, $methods)) {
                $this->$method($value);                
            }elseif(array_key_exists('_'.$key, get_object_vars($this))){
                $this->$key = $value;                
            }else{
                throw new Exception('Invalid entity property');
            }        
        }
        return $this;
    }
@ Andrzej:
- First, proper IDEs come with getter/setter generation build in. So no need to write them!
- I prefer if my IDE can hint me about what properties i can get/set, in other words, hint me what methods i can use on a certain object. No way an IDE can still hint you with above code.
- Your code allows access to all properties. In many, many use-cases there's properties you dont want other code to be able to access.
- .... plenty of more reasons
FYI:
the commands executed on command-line assume this kind of folder tree (when followed from the start of the guide):

- quickstart/layouts/scripts/ (including load.sqlite.php and other .sql files) should be located in the quickstart directory quickstart/scripts/ (its obvious because layouts is all about layouts). So I guess this is also wrong in the application/configs/application.ini file:
...
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts/"
...

- also data/db/ should be located in the quickstart directory quickstart/data/db

This solved the problem with:
% php scripts/load.sqlite.php --withdata
... and created sqlite database (for sqlite database you have to enable sqlite in the php.ini file).

This documentation is really bad and complicated which also makes the use of Zend Framework difficult. I didn't even bother to follow up to the end of this manual. It is reasonable to use only some parts of the framework and make some customised MVC architecture of your own. There are alot better and simpler explanations how to use Zend Framework out there, then it is provided in here.

Cheers
Hello guys, I found this tutorial remake for MySQL:
http://www.webpixel.gr/blog/zend-quickstart-tutorial
php scripts/load.sqlite.php --withdata
this command is totaly ignored by my windows... normal ?
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam dictum nulla ac erat auctor vel lobortis justo pretium. Nam ligula magna, malesuada non gravida quis, luctus et nisi. Integer non neque arcu, sed porta elit. Maecenas sollicitudin vehicula sapien vel condimentum. In hac habitasse platea dictumst. <a href=http://losvazquezsounds.org/>los vazquez sounds</a>
Hi guys,

I Have a problem with db scripts
my data file are in quickstart directory, i have check thausend time all my file but i have always this error :

command : php scripts/load.sqlite.php

' > Writing blabla:
AN ERROR HAS OCCURED
SQLSTATE[HY000]: general error: 1 near "'< CREATE": syntax error

Why, i check all my file no error to the tuto ?
My 3 files in scripts :
directory
quickstart -> scripts

data.sqlite.sql

INSERT INTO guestbook (email, comment, created) VALUES
('ralph.schindler@zend.com',
'Hello! Hope you enjoy this sample zf application!',
DATETIME('NOW'));
INSERT INTO guestbook (email, comment, created) VALUES
('foo@bar.com',
'Baz baz baz, baz baz Baz baz baz - baz baz baz.',
DATETIME('NOW'));

schema.sqlite.sql

CREATE TABLE guestbook (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
email VARCHAR(32) NOT NULL DEFAULT 'noemail@test.com',
comment TEXT NULL,
created DATETIME NOT NULL
);

load.sqlite.php

<?php
/**
* Script pour créer et charger la base
*/

// Initialise le chemin vers l'application et l'autoload
defined('APPLICATION_PATH')
|| define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
set_include_path(implode(PATH_SEPARATOR, array(
APPLICATION_PATH . '/../library',
get_include_path(),
)));
require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance();

// Definit des options CLI
$getopt = new Zend_Console_Getopt(array(
'withdata|w' => 'Load database with sample data',
'env|e-s' => 'Application environment for which to create database (defaults to development)',
'help|h' => 'Help -- usage message',
));
try {
$getopt->parse();
} catch (Zend_Console_Getopt_Exception $e) {
// Mauvaises options passées: afficher l'aide
echo $e->getUsageMessage();
return false;
}

// Si l'aid eest demandée, l'afficher
if ($getopt->getOption('h')) {
echo $getopt->getUsageMessage();
return true;
}

// Initialise des valeurs selon la présence ou absence d'options CLI
$withData = $getopt->getOption('w');
$env = $getopt->getOption('e');
defined('APPLICATION_ENV')
|| define('APPLICATION_ENV', (null === $env) ? 'development' : $env);

// Initialise Zend_Application
$application = new Zend_Application(
APPLICATION_ENV,
APPLICATION_PATH . '/configs/application.ini'
);

// Initialise et récupère la ressoucre DB
$bootstrap = $application->getBootstrap();
$bootstrap->bootstrap('db');
$dbAdapter = $bootstrap->getResource('db');

// Informons l'utilisateur de ce qui se passe (nous créons une base de données
// ici)
if ('testing' != APPLICATION_ENV) {
echo 'Writing Database Guestbook in (control-c to cancel): ' . PHP_EOL;
for ($x = 5; $x > 0; $x--) {
echo $x . "\r"; sleep(1);
}
}

// Vérifions si un fichier pour la base existe déja
$options = $bootstrap->getOption('resources');
$dbFile = $options['db']['params']['dbname'];
if (file_exists($dbFile)) {
unlink($dbFile);
}

// Chargement du fichier de la base de données.
try {
$schemaSql = file_get_contents(dirname(__FILE__) . '/schema.sqlite.sql');
// utilise la connexion directement pour charger le sql
$dbAdapter->getConnection()->exec($schemaSql);
chmod($dbFile, 0666);

if ('testing' != APPLICATION_ENV) {
echo PHP_EOL;
echo 'Database Created';
echo PHP_EOL;
}

if ($withData) {
$dataSql = file_get_contents(dirname(__FILE__) . '/data.sqlite.sql');
// utilise la connexion directement pour charger le sql
$dbAdapter->getConnection()->exec($dataSql);
if ('testing' != APPLICATION_ENV) {
echo 'Data Loaded.';
echo PHP_EOL;
}
}

} catch (Exception $e) {
echo 'AN ERROR HAS OCCURED:' . PHP_EOL;
echo $e->getMessage() . PHP_EOL;
return false;
}

// Ce script sera lancé depuis la ligne de commandes
return true;
?>

lo



CREATE INDEX "id" ON "guestbook" ("id");
(Now browse to "http://localhost/guestbook") didn't work for me.
I had to browse to http://quickstart.local/index.php/guestbook.
I had troubles displaying the guestbook entries using the given code:

Guestbook Entries: <br />
<dl>
<?php foreach ($this->entries as $entry): ?>
<dt><?php echo $this->escape($entry->email) ?></dt>
<dd><?php echo $this->escape($entry->comment) ?></dd>
<?php endforeach ?>
</dl>

To fix it, I had to remove $this->escape() and use the Guestbook getter on comment and email. It now looks like:

Guestbook Entries: <br />
<dl>
<?php foreach ($this->entries as $entry): ?>
<dt><?php echo $entry->getEmail(); ?></dt>
<dd><?php echo $entry->getComment(); ?></dd>
<?php endforeach ?>
</dl>

I don't know is it's a secure way of doing it (removing the escape() doesn't look like a good idea) but it's the only way I found to make the entries show up.
Hope this helps.

+ Add A Comment

Please do not report issues via comments; use the ZF Issue Tracker.

If you have a JIRA/Crowd account, we suggest you login first before commenting.

  • BBCode is allowed in the comment markup

  • Select a Version

    Languages Available

    Components

    Search the Manual