Zend Framework2.0 を試してみる(3)

Zend Framework2.0 を試してみる - Memo
Zend Framework2.0 を試してみる(2) - Memo
の続き。

Create a Model and Database Table

チュートリアルではデータベースアダプターに PDO_Sqite を使うようだ。
まずは設定ファイルにデータベース接続の設定を作る。
zf コマンドで普通に出来た。

$ php bin/zf.php configure db-adapter 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook.db"' production
A db configuration for the production section has been written to the application config file.

$ php bin/zf.php configure db-adapter 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook-testing.db"' testing
A db configuration for the testing section has been written to the application config file.

$ php bin/zf.php configure db-adapter 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook-dev.db"' development
A db configuration for the development section has been written to the application config file.

guestbook.db, guestbook-testing.db, guestbook-dev.db というファイルを quickstart/data/db/ というディレクトリに格納する。

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

スキーマスキーマを読み込んで、テーブルを作るスクリプトを作る。
スキーマのファイルはチュートリアルにあるのをそのまま使う。
とりあえず quickstart/scripts 以下に schema.sqlite.sql, data.sqlite.sql を格納する。
スキーマを読み込みテーブルを作る PHP スクリプト は zf2 では作られていない。

$ diff -u load.sqlite.php.orig load.sqlite.php
--- load.sqlite.php.orig	2010-07-25 00:54:23.000000000 +0900
+++ load.sqlite.php	2010-07-25 00:55:56.000000000 +0900
@@ -13,10 +13,10 @@
 )));
 
 require_once 'Zend/Loader/Autoloader.php';
-Zend_Loader_Autoloader::getInstance();
+Zend\Loader\Autoloader::getInstance();
 
 // Define some CLI options
-$getopt = new Zend_Console_Getopt(array(
+$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',
@@ -43,7 +43,7 @@
     || define('APPLICATION_ENV', (null === $env) ? 'development' : $env);
 
 // Initialize Zend_Application
-$application = new Zend_Application(
+$application = new Zend\Application\Application(
     APPLICATION_ENV,
     APPLICATION_PATH . '/configs/application.ini'
 );

単純に名前空間を変えただけ。
実行してみる。

$ php scripts/load.sqlite.php --withdata
FAILED TO FIND Zend\Db\Adapter\PDO_SQLITE

Fatal error: Class 'Zend\Db\Adapter\PDO_SQLITE' not found in /var/php/zf2/zf/library/Zend/Db/Db.php on line 261

PDO_SQLITE ってのが存在しないみたい。
application/configs/application.ini に設定した resources.db.adapter = "PDO_SQLITE" だと読み込めない。
resources.db.adapter = "PDO\SQLITE" という風に全て変更する。


再度実行する。

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

今度は無事に作れた。


続いて Model を作る。
チュートリアルでは Table Data Gateway パターンと Data Mapper パターンを使う。
Models/DbTable/Gustbook.php には Zend\Db\Table\AbstractTable クラスを継承して作る。
Models/GuestbookMapper.php にマッパーを作る。

$ php bin/zf.php create db-table Guestbook guestbook 
Creating a DbTable at /var/php/zf2/zf/quickstart/application/models/DbTable/Guestbook.php
Updating project profile '/var/php/zf2/zf/quickstart/.zfproject.xml'

$ php bin/zf.php create model GuestbookMapper
Creating a model at /var/php/zf2/zf/quickstart/application/models/GuestbookMapper.php
Updating project profile '/var/php/zf2/zf/quickstart/.zfproject.xml'

$ php bin/zf.php create model Guestbook
Creating a model at /var/php/zf2/zf/quickstart/application/models/Guestbook.php
Updating project profile '/var/php/zf2/zf/quickstart/.zfproject.xml'

んで、チュートリアルのコードを diff ったもの。

$ diff -u Guestbook.php.orig Guestbook.php
--- Guestbook.php.orig	2010-07-25 01:59:05.000000000 +0900
+++ Guestbook.php	2010-07-25 22:35:36.000000000 +0900
@@ -1,10 +1,7 @@
 <?php
+namespace Application\Model\DbTable;
 
-class Application_Model_DbTable_Guestbook extends Zend_Db_Table_Abstract
+class Guestbook extends \Zend\Db\Table\AbstractTable
 {
-
     protected $_name = 'guestbook';
-
-
 }
$ diff GuestbookMapper.php.orig GuestbookMapper.php
2c2,6
< class Application_Model_GuestbookMapper
---
> namespace Application\Model;
> use Application\Model\Guestbook,
>     Application\Model\DbTable\Guestbook as GustbookTable;
> 
> class GuestbookMapper
11,12c15,17
<         if (!$dbTable instanceof Zend_Db_Table_Abstract) {
<             throw new Exception('Invalid table data gateway provided');
---
> 
>         if (!$dbTable instanceof \Zend\Db\Table\AbstractTable) {
>             throw new \Exception('Invalid table data gateway provided');
21c26
<             $this->setDbTable('Application_Model_DbTable_Guestbook');
---
>             $this->setDbTable('Application\Model\DbTable\Guestbook');
26c31
<     public function save(Application_Model_Guestbook $guestbook)
---
>     public function save(Guestbook $guestbook)
42c47
<     public function find($id, Application_Model_Guestbook $guestbook)
---
>     public function find($id, Guestbook $guestbook)
60c65
<             $entry = new Application_Model_Guestbook();
---
>             $entry = new Guestbook();

$ diff -u Guestbook.php.orig Guestbook.php
--- Guestbook.php.orig	2010-07-26 01:46:39.000000000 +0900
+++ Guestbook.php	2010-07-25 03:20:10.000000000 +0900
@@ -1,6 +1,7 @@
 <?php
+namespace Application\Model;
 
-class Application_Model_Guestbook
+class Guestbook
 {
     protected $_comment;
     protected $_created;

名前空間とかを変えただけ。


続いてコントローラを作る。

$ php bin/zf.php create controller Guestbook 

Fatal error: Cannot use Zend\Tool\Project\Profile as Profile because the name is already in use in /var/php/zf2/zf/library/Zend/Tool/Project/Provider/Test.php on line 27

んー。library/Zend/Tool/Project/Provider/Test.php を変更。
Profile ってのがダメみたいなので、同階層にある他のクラスと同じように ProjectProfile にする。

$ diff -u Test.php.orig Test.php
--- Test.php.orig	2010-07-25 02:40:43.000000000 +0900
+++ Test.php	2010-07-25 02:52:25.000000000 +0900
@@ -24,7 +24,7 @@
  * @namespace
  */
 namespace Zend\Tool\Project\Provider;
-use Zend\Tool\Project\Profile;
+use Zend\Tool\Project\Profile as ProjectProfile;
 
 /**
  * @uses       \Zend\Tool\Project\Provider\AbstractProvider
@@ -45,7 +45,7 @@
      * @param \Zend\Tool\Project\Profile $profile
      * @return bool
      */
-    public static function isTestingEnabled(Profile $profile)
+    public static function isTestingEnabled(ProjectProfile $profile)
     {
         $profileSearchParams = array('testsDirectory');
         $testsDirectory = $profile->search($profileSearchParams);
@@ -62,7 +62,7 @@
      * @param string $moduleName
      * @return \Zend\Tool\Project\Profile\Resource
      */
-    public static function createApplicationResource(Profile $profile, $controllerName, $actionName, $moduleName = null)
+    public static function createApplicationResource(ProjectProfile $profile, $controllerName, $actionName, $moduleName = null)
     {
         if (!is_string($controllerName)) {
             throw new Exception('Zend_Tool_Project_Provider_View::createApplicationResource() expects \"controllerName\" is the name of a controller resource to create.');
@@ -99,7 +99,7 @@
      * @param string $libraryClassName
      * @return \Zend\Tool\Project\Profile\Resource
      */
-    public static function createLibraryResource(Profile $profile, $libraryClassName)
+    public static function createLibraryResource(ProjectProfile $profile, $libraryClassName)
     {
         $testLibraryDirectoryResource = $profile->search(array('TestsDirectory', 'TestLibraryDirectory'));

再度実行。

$ php bin/zf.php create controller Guestbook

Warning: include_once(Zend/Tool/Framework/Client/HelpSystem.php): failed to open stream: No such file or directory in /var/php/zf2/zf/library/Zend/Loader.php on line 151

むー。
library/Zend/Tool/Framework/Client/Console.php の HelpSystem(); の名前空間がおかしい。

$ diff -u Console.php.orig Console.php
--- Console.php.orig	2010-07-22 22:28:59.000000000 +0900
+++ Console.php	2010-07-25 03:08:10.000000000 +0900
@@ -185,18 +185,18 @@
     {
         $response = $this->_registry->getResponse();
 
-        $response->addContentDecorator(new ResponseDecorator\AlignCenter());
-        $response->addContentDecorator(new ResponseDecorator\Indention());
-        $response->addContentDecorator(new ResponseDecorator\Blockize());
+        $response->addContentDecorator(new Console\ResponseDecorator\AlignCenter());
+        $response->addContentDecorator(new Console\ResponseDecorator\Indention());
+        $response->addContentDecorator(new Console\ResponseDecorator\Blockize());
 
         if (function_exists('posix_isatty')) {
-            $response->addContentDecorator(new ResponseDecorator\Colorizer());
+            $response->addContentDecorator(new Console\ResponseDecorator\Colorizer());
         }
         
         $response->addContentDecorator(new \Zend\Tool\Framework\Client\Response\ContentDecorator\Separator())
             ->setDefaultDecoratorOptions(array('separator' => true));
 
-        $optParser = new ArgumentParser();
+        $optParser = new Console\ArgumentParser();
         $optParser->setArguments($_SERVER['argv'])
             ->setRegistry($this->_registry)
             ->parse();
@@ -214,7 +214,7 @@
         $response = $this->_registry->getResponse();
 
         if ($response->isException()) {
-            $helpSystem = new HelpSystem();
+            $helpSystem = new Console\HelpSystem();
             $helpSystem->setRegistry($this->_registry)
                 ->respondWithErrorMessage($response->getException()->getMessage(), $response->getException())
                 ->respondWithSpecialtyAndParamHelp(

.zfproject.xml にゴミが出来てる可能性があるので、Controller に関する所で Guestbook となっているのを削除し再度実行。

$ php bin/zf.php create controller Guestbook
Creating a controller at /var/php/zf2/zf/quickstart/application/controllers/GuestbookController.php
Creating an index action method in controller Guestbook
Creating a view script for the index action method at /var/php/zf2/zf/quickstart/application/views/scripts/guestbook/index.phtml
Creating a controller test file at /var/php/zf2/zf/quickstart/tests/application/controllers/GuestbookControllerTest.php
Updating project profile '/var/php/zf2/zf/quickstart/.zfproject.xml'

なぜかコントローラクラスだけ zf2 でジェネレートされた。
indexAction() に以下を追加する。

<?php
    public function indexAction()
    {
        $guestbook = new Application\Model\GuestbookMapper();
        $this->view->entries = $guestbook->fetchAll();
    }

views/scripts/guestbook/index.phtml にも以下を追加。

<p><a href="<?php echo $this->url(
    array(
        'controller' => 'guestbook',
        'action'     => 'sign'
    ),
    'default',
    true) ?>">Sign Our Guestbook</a></p>

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>

ブラウザで http://localhost/guestbook にアクセスしたら、登録した初期データが表示される。