モデルとデータベーステーブルの作成
始める前にちょっと考えてみましょう。これらのクラスはどこにあって、それをどのように探すのでしょうか?
わたしたちが作成したデフォルトのプロジェクトでは、一つのオートローダーがインスタンス化されます。
そこへ、他のクラスを探せるよう別のオートローダーを付け加えることができます。
MVC の様々なクラスはふつう一つのツリー -- ここでは application/ --
に集まっていて、ほとんどの場合には共通のプレフィックスを持っていてほしいものです。
Zend_Controller_Front は、独立したミニアプリケーション、
すなわち "モジュール" という考え方を採用しています。モジュールは zf
ツールが application/ 以下に設定するディレクトリ構造を模倣しており、
その中の全てのクラスはモジュール名を共通のプレフィックスとして持っているものと見なされます。
application/ はそれ自体が一つのモジュール -- "default" または "application"
モジュール -- です。以上を踏まえてこのディレクトリ下にあるリソースのオートロードを設定していきたいと思います。
Zend_Application_Module_Autoloader は、あるモジュールの様々なリソースを
適切なディレクトリに対応付けるために必要となる機能を提供し、同時に、名前の付け方の規約も提供します。
このクラスのインスタンスは、デフォルトではブートストラップ・オブジェクトの初期化時に作成され、
アプリケーションのブートストラップでは "Application" というプレフィックスをデフォルトで使用します。
そのため、モデル、フォーム、テーブル・クラスはどれも、プレフィックス "Application_" で始めます。
では、ゲストブックを作っていくことにしましょう。一般的にはコメント、
タイムスタンプ、それからたまにメールアドレスを持つ単純なリストになります。
それらをデータベースに保存するとしたら、各エントリーのユニークな識別子も欲しいかも知れません。
エントリーを保存したり特定のエントリーを取ってきたり全エントリーを読み出したくなることでしょう。
そうだとすると、簡単なゲストブックモデルの API はこのようになりそうです。
// application/models/Guestbook.php
__get() と __set() は、
各エントリーのプロパティにアクセスする便利な仕組みと、他のゲッター、セッターのプロキシを提供してくれます。
また、オブジェクト中の許可したプロパティのみアクセス可能にするのにも役立ちます。
find() と fetchAll() は単一のエントリーや
全てのエントリーをフェッチする機能を提供し、 save() は
一つのエントリーをデータストアに保存する面倒を見ます。
ここでようやく、データベース設定について考え始めることができます。
まず Db リソースを初期化する必要があります。
Layout リソースと View リソースから Db
リソースの設定を準備できます。これには zf configure db-adapter コマンドが使えます。
% zf configure db-adapter \
> 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook.db"' \
> production
A db configuration for the production has been written to the application config file.
% zf configure db-adapter \
> 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook-testing.db"' \
> testing
A db configuration for the production has been written to the application config file.
% zf configure db-adapter \
> 'adapter=PDO_SQLITE&dbname=APPLICATION_PATH "/../data/db/guestbook-dev.db"' \
> development
A db configuration for the production has been written to the application config file.
ここで application/configs/application.ini ファイルの相当する部分に
以下の行が追加されているのが見付かるので、編集します。
; application/configs/application.ini
[production]
; ...
resources.db.adapter = "PDO_SQLITE"
resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook.db"
[testing : production]
; ...
resources.db.adapter = "PDO_SQLITE"
resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-testing.db"
[development : production]
; ...
resources.db.adapter = "PDO_SQLITE"
resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-dev.db"
設定ファイルが最終的に以下のようになるようにしてください。
; application/configs/application.ini
[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
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.db.adapter = "PDO_SQLITE"
resources.db.params.dbname = APPLICATION_PATH "/../data/db/guestbook-dev.db"
データベースは data/db/ に保存されることに注意しましょう。
ディレクトリを作って全ユーザーに書き込み権限を与えます。ユニックスライクなシステムでは、
次のようにすれば設定できます。
% mkdir -p data/db; chmod -R a+rwX data
Windows では、エクスプローラでディレクトリを作り、
全ユーザーがそのディレクトリに書き込めるようアクセス権を設定する必要があります。
この段階でデータベース接続が行えます。今の例では application/data/
ディレクトリ内にある Sqlite データベースへの接続です。では、ゲストブックのエントリーを入れる簡単なテーブルを設計しましょう。
-- scripts/schema.sqlite.sql
--
-- この SQL からデータベーススキーマをロードする必要があります。
'noemail@test.com'"id""guestbook" ("id");
それから、素晴らしい仕事ができるように、数行、アプリケーションを面白くするする情報を作りましょう。
-- scripts/data.sqlite.sql
--
-- 以下の SQL 文でデータベースに生命を吹き込めます。
'ralph.schindler@zend.com',
'Hello! Hope you enjoy this sample zf application!',
DATETIME('NOW''foo@bar.com',
'Baz baz baz, baz baz Baz baz baz - baz baz baz.',
DATETIME('NOW'));
これでスキーマができ、データもいくらか定義できました。それでは一緒にスクリプトを書いてこのデータベースの構築を実行しましょう。
普通は、プロダクション環境でこういったことは必要ありませんが、このスクリプトがあれば開発者が必要なデータベースを手元で構築して、アプリケーションの作業に全力投球するのを助けてくれるでしょう。
以下の内容で、scripts/load.sqlite.php としてスクリプトを作ってください。
// scripts/load.sqlite.php
/**
* データベースを作成して読み込むスクリプト
*/
// アプリケーションパスとオートロードの初期化
'APPLICATION_PATH''APPLICATION_PATH''/../application''/../library''Zend/Loader/Autoloader.php'// CLI 用のオプション
'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'// オプションが不正な場合に使用法を表示
// ヘルプが要求された場合に使用法を表示
'h'// CLI オプションの有無に応じて値を初期化
'w''e''APPLICATION_ENV''APPLICATION_ENV''development' : $env);
// Zend_Application の初期化
'/configs/application.ini'
);
// DB リソースの初期化と読み込み
$bootstrap = $application->getBootstrap();
$bootstrap->bootstrap('db');
$dbAdapter = $bootstrap->getResource('db');
// やっていることをユーザーに通知
// (実際にここでデータベースを作る)
'testing''Writing Database Guestbook in (control-c to cancel): '"\r"// データベースファイルが既にないかチェック
'resources''db']['params']['dbname'// このブロックでスキーマファイルから読み込んだ実際のステートメントを実行
'/schema.sqlite.sql');
// use the connection directly to load sql in batches
'testing''Database Created''/data.sqlite.sql');
// use the connection directly to load sql in batches
'testing''Data Loaded.''AN ERROR HAS OCCURED:'// 大抵の場合、このスクリプトはコマンドラインから走らせて true を返す
このスクリプトを実行しましょう。ターミナルか DOS のコマンドラインから以下を実行してください。
% php scripts/load.sqlite.php --withdata
以下のような出力を目にすると思います。
path/to/ZendFrameworkQuickstart/scripts$ php load.sqlite.php --withdata
Writing Database Guestbook in (control-c to cancel):
1
Database Created
Data Loaded.
これでゲストブックアプリケーションのためにきちんと動くデータベースとテーブルができました。
次のステップはアプリケーションのコードを作成することです。
これにはデータソース(ここでは Zend_Db_Table を使います)と、
そのデータソースをドメインモデルに繋げる役目のデータマッパーを構築することが含まれます。
最後に、既存のエントリーの表示と新規エントリーの処理をモデルに結び付けるコントローラーも作ります。
ここではデータソースへの接続に» テーブルデータゲートウェイ を使います。
Zend_Db_Table がこの機能を提供してくれます。
始めるにあたって Zend_Db_Table ベースのクラスを作りましょう。
レイアウトとデータベースアダプタでやった時と同じように、zf
ツールの力を借りることができます。create db-table コマンドを使うのです。
これは最低で 2 つの引数をとります。参照させるクラスと、対応付けるデータベーステーブルの名前です。
% zf create db-table Guestbook guestbook
Creating a DbTable at application/models/DbTable/Guestbook.php
Updating project profile 'zfproject.xml'
ディレクトリツリーを見てみると、新規ディレクトリ application/models/DbTable/
が作られてファイル Guestbook.php が作られているのが分かります。
ファイルを開くと以下の内容になっています。
// application/models/DbTable/Guestbook.php
/**
* This is the DbTable class for the guestbook table.
*//** Table name */'guestbook';
}
クラスのプレフィックス Application_Model_DbTable に注目しましょう。
最初の部分がモジュールのクラスプレフィックス "Application" で、その後にコンポーネント
"Model_DbTable" がきます。後者はモジュールのディレクトリ models/DbTable/
に対応付けられています。
Zend_Db_Table を拡張する際に必要なのはテーブル名と場合により主キーを
("id" でなければ)与えることだけです。
では » データマッパー
を作成しましょう。データマッパー はドメインオブジェクトをデータベースに対応付けます。
ここではモデル Application_Model_Guestbook をデータソース
Application_Model_DbTable_Guestbook に対応付けることになります。
データマッパーの典型的な API は次のようになるでしょう。
// application/models/GuestbookMapper.php
こうしたメソッドの他に、テーブルデータゲートウェイを設定してそこからデータを取り出すメソッドを追加します。
クラスの最初の形を作成するのに CLI の zf ツールを使います。
% zf create model GuestbookMapper
Creating a model at application/models/GuestbookMapper.php
Updating project profile '.zfproject.xml'
次に application/models/GuestbookMapper.php にあるクラス
Application_Model_GuestbookMapper を編集して下記の通りにします。
// application/models/GuestbookMapper.php
'Invalid table data gateway provided''Application_Model_DbTable_Guestbook''email''comment' => $guestbook->getComment(),
'created''Y-m-d H:i:s''id''id = ?'
これでモデルクラスが作れます。ここでもコマンド zf create model を使います。
% zf create model Guestbook
Creating a model at application/models/Guestbook.php
Updating project profile '.zfproject.xml'
この空の PHP クラスを修正して、コンストラクタでも setOptions()
メソッドでも、データの配列からモデルを生成するのを簡単にします。application/models/Guestbook.php
中の最終的なモデルクラスはこのようになるはずです。
// application/models/Guestbook.php
'set''mapper''Invalid guestbook property''get''mapper''Invalid guestbook property''set'
最後に、以上の要素を全て一つに繋げます。データベース内の既存のエントリーを一覧表示する
ゲストブック用のコントローラを作りましょう。
新しいコントローラを作るには zf create controller コマンドを使います。
% zf create controller Guestbook
Creating a controller at
application/controllers/GuestbookController.php
Creating an index action method in controller Guestbook
Creating a view script for the index action method at
application/views/scripts/guestbook/index.phtml
Creating a controller test file at
tests/application/controllers/GuestbookControllerTest.php
Updating project profile '.zfproject.xml'
このコマンドによって application/controllers/GuestbookController.php の中に
GuestbookController が作られ、そこには一つのアクションメソッド
indexAction() が出来ています。また、このコントローラーの
ビュースクリプト用ディレクトリ application/views/scripts/guestbook/
とインデックスアクション用のビュースクリプトも作成されます。
ゲスブックの全エントリーを表示する入り口用のページとして "index" アクションを使います。
では、基本的なアプリケーションロジックを一息に作ってしまいましょう。 indexAction()
へやって来るとゲストブックの全エントリーを表示します。これは次のようになります。
// application/controllers/GuestbookController.php
それからもちろんこれに使うビュースクリプトが必要です。
application/views/scripts/guestbook/index.phtml を以下のように編集します。
<!-- application/views/scripts/guestbook/index.phtml -->
<p><a href="<?php echo $this->url(
array(
'controller' => 'guestbook',
'action' => 'sign'
),
'default',
true) ?>"
Note: チェックポイント
ここで "http://localhost/guestbook" にアクセスしてみましょう。
ブラウザには次のように表示されるはずです。
Note: データローダースクリプトの使用
この節で導入したデータローダースクリプト(scripts/load.sqlite.php)は
定義した環境のそれぞれでデータベースを作りサンプルデータを読み込むのに使用できます。
内部では、多くのコマンドラインスイッチを提供できるようにしてくれる
Zend_Console_Getopt を利用しています。"-h" または "--help"
スイッチを渡すと使用可能なオプションを提示します。
"-e" スイッチを使うと APPLICATION_ENV 定数に使用する値を指定できます。
-- 定義した各環境で順に SQLite データベースを作れるようになるのです。
デプロイ時に、アプリケーション用に選んだ環境で確実にこのスクリプトを走らせるようにしてください。