intro
Zend Frameworkで関連テーブルを使用した場合の処理例です。ソースコードはこちらからダウンロードできます。
また、デモサイトより動作を確認できます。
また、デモサイトより動作を確認できます。
1.bootstrap.phpとconfig.iniの作成
以下のように
環境に合わせて
以下のように
環境に合わせて
この記事では以下のSQLを使用しました(MySQL)。
application/bootstrap.php
ファイルを作成します。環境に合わせて
yourBaseUrl
を適切に設定してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?php set_include_path('../library' . PATH_SEPARATOR . get_include_path()); define('APP_BASE', '../application'); define('CONFIG_PATH', APP_BASE . '/config.ini'); require_once 'Zend/Controller/Front.php'; require_once 'Zend/Layout.php'; require_once 'Zend/Db.php'; require_once 'Zend/Config/Ini.php'; require_once 'Zend/Db/Table/Abstract.php'; $layout = Zend_Layout::startMvc(); //$layout->getView()->baseUrl = '/yourBaseUrl'; $config = new Zend_Config_Ini(CONFIG_PATH, 'staging'); $params = $config->database->params->toArray(); $params['options'][Zend_Db::CASE_FOLDING] = Zend_Db::CASE_LOWER; $dbAdapter = Zend_Db::factory($config->database->adapter, $params); Zend_Db_Table_Abstract::setDefaultAdapter($dbAdapter); Zend_Controller_Front::run(APP_BASE . '/controllers'); |
以下のように
application/config.ini
ファイルを作成します。環境に合わせて
database.params
以下を変更してください。
1 2 3 4 5 6 |
[staging] database.adapter = pdo_mysql database.params.host = localhost database.params.username = db_user database.params.password = db_password database.params.dbname = db_name |
この記事では以下のSQLを使用しました(MySQL)。
1 2 3 4 5 6 7 8 9 10 11 12 |
CREATE TABLE projects ( id integer auto_increment NOT NULL PRIMARY KEY, project_name varchar(100) NOT NULL ); CREATE TABLE projects_members ( id integer auto_increment NOT NULL PRIMARY KEY, project_id integer NOT NULL, member_id integer NOT NULL ); |
2.モデルの作成
以下のように
以下のように
次に以下のように
次に以下のように
application/models/Projects.php
ファイルを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?php require_once 'Zend/Db/Table/Abstract.php'; require_once 'Zend/Filter/Input.php'; require_once APP_BASE . '/models/ProjectsMembers.php'; require_once APP_BASE . '/models/Members.php'; class Projects extends Zend_Db_Table_Abstract { protected $_name = 'projects'; protected $_dependentTables = array( 'ProjectsMembers' ); public function getOutputFilter($data = null) { $members = new Members(); $member_options = $members->getOptions(); // add other filters $filters = array( 'ProjectsMembers' => array(array('ArrayValue', $member_options)) ); $of = new Zend_Filter_Input($filters, null, $data); $of->addFilterPrefixPath('My_Filter', 'My/Filter/'); return $of; } } |
以下のように
application/models/ProjectsMembers.php
ファイルを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<?php require_once 'Zend/Db/Table/Abstract.php'; class ProjectsMembers extends Zend_Db_Table_Abstract { protected $_name = 'projects_members'; protected $_referenceMap = array( 'Project' => array( 'columns' => array('project_id'), 'refTableClass' => 'Projects', 'refColumns' => array('id'), 'onDelete' => self::CASCADE ), 'Member' => array( 'columns' => array('member_id'), 'refTableClass' => 'Members', 'refColumns' => array('id'), 'onDelete' => self::CASCADE ) ); } |
次に以下のように
application/models/forms/ProjectForm.php
ファイルを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<?php require_once 'Zend/Form.php'; require_once APP_BASE . '/models/forms/ProjectMemberSubForm.php'; class ProjectForm extends Zend_Form { public function __construct() { parent::__construct(); $project_name = $this->createElement('text', 'project_name'); $project_name->setLabel('project_name') ->setRequired(true) ->addFilter('stringTrim') ->addValidator('stringLength', false, array(1,100)); $this->addElements(array( $project_name )); $sub = new ProjectMemberSubForm(); $sub->setLegend('ProjectsMembers'); $this->addSubForm($sub, 'ProjectsMembers'); } } |
次に以下のように
application/models/forms/ProjectMemberSubForm.php
ファイルを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?php require_once 'Zend/Form/SubForm.php'; require_once APP_BASE . '/models/Members.php'; class ProjectMemberSubForm extends Zend_Form_SubForm { public function __construct() { $members = new Members(); $member_options = $members->getOptions(); parent::__construct(); $member_id = $this->createElement('multiselect', 'member_id'); $member_id->setLabel('member_id') ->setMultiOptions($member_options) ->setRequired(true) ->addFilter('stringTrim') ->addValidator('int') ->addValidator('inArray', false, array(array_keys($member_options))); $this->addElements(array( $member_id )); } } |
3.コントローラの作成
以下のように
前回作成した
application/constorllers/ProjectController.php
ファイルを作成します。前回作成した
My_Controller_Simple
クラスを継承しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
<?php require_once 'My/Controller/Simple.php'; require_once APP_BASE . '/models/Projects.php'; require_once APP_BASE . '/models/forms/ProjectForm.php'; class ProjectController extends My_Controller_Simple { protected $_session_name = "Project"; protected $_table_class = "Projects"; protected $_form_class = "ProjectForm"; protected function _executeInsert($table, $values) { $dept_values['ProjectsMembers'] = $values['ProjectsMembers']; unset($values['ProjectsMembers']); $row = $table->createRow(); $row->setFromArray($values); $id = $row->save(); $pm_table = new ProjectsMembers(); $pm_values['project_id'] = $id; foreach ($dept_values['ProjectsMembers']['member_id'] as $member_id) { $pm_values['member_id'] = $member_id; $pm_row = $pm_table->createRow(); $pm_row->setFromArray($pm_values); $pm_row->save(); } } protected function _executeUpdate($table, $id, $values) { $dept_values['ProjectsMembers'] = $values['ProjectsMembers']; unset($values['ProjectsMembers']); $row = $table->find($id)->current(); $row->setFromArray($values); $row->save(); $members = $dept_values['ProjectsMembers']['member_id']; $rowset = $row->findDependentRowset('ProjectsMembers'); foreach ($rowset as $pm_row) { $key = array_search($pm_row->member_id, $members); if ($key === FALSE) { $pm_row->delete(); } else { unset($members[$key]); } } $pm_table = new ProjectsMembers(); $pm_values['project_id'] = $id; foreach ($members as $member_id) { $pm_values['member_id'] = $member_id; $pm_row = $pm_table->createRow(); $pm_row->setFromArray($pm_values); $pm_row->save(); } } protected function _executeDelete($table, $id) { $row = $table->find($id)->current(); $row->delete(); } protected function _executeFind($table, $id) { $row =$table->find($id)->current(); if ($row) { $values = $row->toArray(); $values['ProjectsMembers']['member_id'] = array(); $rowset = $row->findDependentRowset('ProjectsMembers'); foreach ($rowset as $pm_row) { $values['ProjectsMembers']['member_id'][] = $pm_row->member_id; } return $values; } return null; } protected function _getOutputFilter($data = null) { $projects = new Projects(); return $projects->getOutputFilter($data); } public function preDispatch() { $this->view->name = "project"; $this->view->of = $this->_getOutputFilter(); } public function indexAction() { $this->_forward('list'); } } |
4.ビューの作成
以下のように
以下のように
以下のように
以下のように
以下のように
application/views/scripts/project/list.phtml
ファイルを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<h1><?= $this->translate($this->name . '.title.list') ?></h1> <?php if (!$this->list) : ?> <span><?= $this->translate($this->name . 'label.no_data') ?></span> <?php else : ?> <a href="<?=$this->url(array('action'=>'add'))?>"> <?= $this->translate($this->name . '.label.new') ?></a> <table> <?php $this->header = true; ?> <?php foreach($this->list as $row) : ?> <?php $values = $row->toArray(); ?> <?php if ($this->header) : ?> <tr> <?php foreach($values as $key => $value) : ?> <th><?= $this->translate($key) ?></th> <?php endforeach; ?> <th><?= $this->translate('detail') ?></th> <th><?= $this->translate('edit') ?></th> <th><?= $this->translate('delete') ?></th> <?php $this->header = false; ?> </tr> <?php endif; ?> <tr> <?php foreach($values as $key => $value) : ?> <td><?= $this->escape($value) ?></td> <?php endforeach; ?> <td><a href="<?=$this->url(array('action'=>'detail'))?>?id=<?=$row->id?>"> <?= $this->translate('detail') ?></a></td> <td><a href="<?=$this->url(array('action'=>'update'))?>?id=<?=$row->id?>"> <?= $this->translate('edit') ?></a></td> <td><a href="<?=$this->url(array('action'=>'delete'))?>?id=<?=$row->id?>"> <?= $this->translate('delete') ?></a></td> </tr> <?php endforeach; ?> </table> <span><?= $this->translate($this->name . '.label.max') ?></span> <?php endif; ?> |
以下のように
application/views/scripts/project/detail.phtml
ファイルを作成します。
1 2 3 4 5 6 7 8 9 |
<h1><?= $this->translate($this->name . '.title.detail') ?></h1> <?php if ($this->values) : ?> <?php $this->of->setData($this->values); ?> <?php $values = $this->of->getEscaped(); ?> <?= $this->partial('common/partList.phtml', array('datalist'=>$values)) ?> <?php endif; ?> <?php if ($this->form) : ?> <?= $this->form ?> <?php endif; ?> |
以下のように
application/views/scripts/project/form.phtml
ファイルを作成します。
1 2 |
<h1><?= $this->translate($this->name . '.title.' . $this->action) ?></h1> <?= $this->form ?> |
以下のように
application/views/scripts/project/finish.phtml
ファイルを作成します。
1 2 3 |
<h1><?= $this->translate($this->name . '.title.finish.' . $this->action) ?></h1> <a href="<?=$this->url(array('action'=>'list'))?>"> <?= $this->translate('back') ?></a> |
以下のように
application/views/scripts/common/partList.phtml
ファイルを作成します。
1 2 3 4 5 6 7 8 9 10 11 12 |
<dl> <?php foreach($this->datalist as $key => $value) : ?> <dt><?= $this->translate($key) ?></dt> <?php if (is_array($value)) : ?> <dd> <?= $this->partial('common/partList.phtml', array('datalist'=>$value)) ?> </dd> <?php else : ?> <dd><?= $value ?></dd> <?php endif; ?> <?php endforeach; ?> </dl> |
5.確認
Webサーバにアクセスして関連テーブルへの追加/更新/削除/閲覧機能が実装されていることを確認してみてください。