S2Erdは、ERDデザインツールのデータからZend_Db_TableクラスのPHPソースを生成します。
対応しているERDデザインツール
「Zend_ControllerでS2Containerを使用する」にしたがって、Zend Frameworkのプロジェクトを作成します。
ダウンロード.
PEAR インストール.
S2Erd-version.tgzをダウンロードし、pear install を実行します。
% pear install /path/to/S2Erd-version.tgz install ok: channel://pear.php.net/S2Erd-version % pear list ・・・ S2Erd version state ・・・ %
zf.iniファイルの作成.
ホームディレクトリに次のzf.iniファイルを作成します。
% cat ~/zf.ini basicloader.classes.0 = "seasar_erd_util_zend_Manifest" php.include_path = ".:/usr/lib/php:/path/to/zf/project/library" %
S2Erdの設定を行うs2erd.phpをapplication/configsディレクトリに作成します。
S2Erd用のオートローダーを設定することで、ERDデザインツールのデータから、直接PHPのTableクラスを定義することができます。
テーブル定義が不定の間は、このオートローダーでTableクラス定義を読み込み、テーブル定義が確定した後は、次の「Zend_Toolコマンド」で
Tableクラス定義をファイルに出力します。
s2erd_autoload.phpの作成.
S2Erd用のAutoload設定を行うs2erd_autoload.phpをapplication/configsディレクトリに作成します。
Bootstrap.phpの編集.
アプリケーションのBootstrapでs2erd_autoload.phpをrequireします。(_initAutoloadメソッド)
Zend_Tool の zf コマンドを実行し、次のコマンドが追加されているかどうかを確認します。
% zf.sh --help
. . .
. . .
. . .
A5Model
zf create a5model a5er-file[=<project/var/db/project.a5er>]
ERMModel
zf create erm-model erm-file[=<project/var/db/project.erm>]
MWBModel
zf create mwb-model schema[=mydb] mwb-file[=<project/var/db/project.mwb>]
%
使用しているERDデザインツール用のコマンドを実行します。Tableクラス定義ファイルは、application/models/DbTable ディレクトリに出力されます。
zfコマンドのオプションとして「--pretend」を付加した場合は、標準出力にTableクラス定義が出力されます。(ファイル出力されません。)
サンプルとして、var/db ディレクトリに次のERDデザインツールのデータファイルを用意しています。
テーブル定義はZend_Dbドキュメントのサンプルデータベースを参照下さい。
例として、MySQL Workbench(project.mwb)を対象とするMWBModelコマンドを実行してみます。
% ls application/models/DbTable
% zf create mwb-model s2
MySQL Workbench File: /project/var/db/project.mwb
create : application/models/DbTable/Abstract.php
create : application/models/DbTable/Accounts.php
create : application/models/DbTable/Bugs.php
create : application/models/DbTable/BugsProducts.php
create : application/models/DbTable/Products.php
% cat application/models/DbTable/Bugs.php
<?php
/**
* @S2Component('autoBinding' => 'none')
*/
class Model_DbTable_Bugs extends Model_DbTable_Abstract {
const PNAME = 'bugs';
const LNAME = 'bugs';
const COMMENT = '';
public static $FIELDS = array(
'bug_id' => array(
'pname' => 'bug_id',
'lname' => 'bug_id',
'type' => 'INT',
'type_opt' => null,
'length' => -1,
'scale' => -1,
'precision' => -1,
'nn' => true,
'pk' => true,
'fk' => false,
'default' => '',
'comment' => '',
'options' => null),
. . . . .
. . . . .
. . . . .
'verified_by' => array(
'pname' => 'verified_by',
'lname' => 'verified_by',
'type' => 'VARCHAR',
'type_opt' => null,
'length' => 100,
'scale' => -1,
'precision' => -1,
'nn' => false,
'pk' => false,
'fk' => true,
'default' => '',
'comment' => '',
'options' => null));
public static $FILTERS = array(
'bug_id' => array('Int'));
public static $VALIDATORS = array(
'bug_id' => array('presence' => 'required', 'Int'),
'bug_description' => array('allowEmpty' => 'true', array('StringLength', 0, 100, 'UTF-8')),
'bug_status' => array('allowEmpty' => 'true', array('StringLength', 0, 20, 'UTF-8')),
'reported_by' => array('allowEmpty' => 'true', array('StringLength', 0, 100, 'UTF-8')),
'assigned_to' => array('allowEmpty' => 'true', array('StringLength', 0, 100, 'UTF-8')),
'verified_by' => array('allowEmpty' => 'true', array('StringLength', 0, 100, 'UTF-8')));
protected $_name = 'bugs';
protected $_primary = array('bug_id');
protected $_sequence = false;
protected $_dependentTables = array('Model_DbTable_BugsProducts');
protected $_referenceMap = array(
'ReportedBy' => array(
'columns' => array('reported_by'),
'refTableClass' => 'Model_DbTable_Accounts',
'refColumns' => array('account_name')),
'AssignedTo' => array(
'columns' => array('assigned_to'),
'refTableClass' => 'Model_DbTable_Accounts',
'refColumns' => array('account_name')),
'VerifiedBy' => array(
'columns' => array('verified_by'),
'refTableClass' => 'Model_DbTable_Accounts',
'refColumns' => array('account_name')));
}
%
生成されたModel_DbTable_BugsクラスのLNAMEや$FIELDSのlname値は、 A5:SQLやER Masterを使用している場合に日本語カラム名となります。
サンプルとして、accountsテーブルのTableクラスのUnitTestを作成します。UnitTestは、tests/application/models/DbTableディレクトリ にAccountsTest.php として作成します。
class Model_DbTable_AccountsTest extends PHPUnit_Framework_TestCase {
public function testFetchAll() {
$this->assertEquals(5, count($this->model->fetchAll()));
}
public function setUp() {
$this->model = s2get('Model_DbTable_Accounts');
}
public function tearDown() {
$this->model = null;
}
}
UnitTestの実行結果は次になります。
% phpunit application/models/DbTable PHPUnit 3.4.2 by Sebastian Bergmann. . Time: 1 second OK (1 test, 1 assertion) %
Model_DbTable_Accountsクラスは未作成ですが、S2ErdのAutoloadにより動的にクラス定義が実施されるため、 Tableモデルを使用することができます。
サンプルとして、TableモデルやDBアダプタを使用するサービスクラスをapplication/servicesディレクトリ にSample.php として作成します。
class Service_Sample {
public function setModel(Model_DbTable_Bugs $model) {
$this->model = $model;
}
public function setAdapter(Zend_Db_Adapter_Abstract $adapter) {
$this->adapter = $adapter;
}
public function fetchAllBugs() {
return $this->model->fetchAll()->toArray();
}
public function fetchProductBugDescriptions() {
$select = $this->adapter->select()->from(array('bp' => Model_DbTable_BugsProducts::PNAME), array());
$select->joinLeft(array('b' => Model_DbTable_Bugs::PNAME), 'b.bug_id = bp.bug_id', array('bug_description'));
$select->joinLeft(array('p' => Model_DbTable_Products::PNAME), 'p.product_id = bp.product_id', array('product_name'));
return $this->adapter->fetchAll($select);
}
}
TableモデルやDBアダプタはセッターメソッドでインジェクションされます。
検索を行うSQLの発行についてはDBアダプタを利用することが多く、新規作成、更新、削除処理についてはTableモデルを使用します。
SampleサービスクラスのUnitTestを作成します。UnitTestは、tests/application/servicesディレクトリ にSampleTest.php として作成します。
class Service_SampleTest extends PHPUnit_Framework_TestCase {
public function testFetchAllBugs() {
$this->assertEquals(3, count($this->service->fetchAllBugs()));
}
public function testFetchAllBugsWithAccounts() {
$rows = $this->service->fetchProductBugDescriptions();
$this->assertEquals(6, count($rows));
}
public function setUp() {
require(APPLICATION_PATH . '/dicons/dicon.php'); // 共通設定ファイル
$this->service = s2get('Service_Sample');
}
public function tearDown() {
$this->service = null;
}
}
UnitTestの実行結果は次になります。
% phpunit application/services PHPUnit 3.4.2 by Sebastian Bergmann. .. Time: 0 seconds OK (2 tests, 2 assertions) %
サービスクラスをアクションコントローラで使用する方法については、「アクションメソッドでS2Containerを利用する」 を参照ください。
| © Copyright The Seasar Foundation and the others 2005-2010, all rights reserved. |