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. |