Home > Zend_Db > Zend Frameworkでの関連テーブルの使用例

Zend Frameworkでの関連テーブルの使用例

intro
Zend Frameworkで関連テーブルを使用した場合の処理例です。ソースコードはこちらからダウンロードできます。
また、デモサイトより動作を確認できます。

1.bootstrap.phpとconfig.iniの作成
以下のようにapplication/bootstrap.phpファイルを作成します。
環境に合わせてyourBaseUrlを適切に設定してください。

<?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以下を変更してください。

[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)。

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ファイルを作成します。

<?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ファイルを作成します。

<?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ファイルを作成します。

<?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ファイルを作成します。

<?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クラスを継承しています。

<?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ファイルを作成します。

 
<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ファイルを作成します。

 
<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ファイルを作成します。

 
<h1><?= $this->translate($this->name . '.title.' . $this->action) ?></h1>
 
<?= $this->form ?>

以下のようにapplication/views/scripts/project/finish.phtmlファイルを作成します。

 
<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ファイルを作成します。

 
<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サーバにアクセスして関連テーブルへの追加/更新/削除/閲覧機能が実装されていることを確認してみてください。

Comments:0

Comment Form
Remember personal info

Trackbacks:0

Trackback URL for this entry
http://www.oplabo.jp/article/35/trackback
Listed below are links to weblogs that reference
Zend Frameworkでの関連テーブルの使用例 from Open Programming Laboratory

Home > Zend_Db > Zend Frameworkでの関連テーブルの使用例

English
Search
Feeds

Return to page top