Home > Zend_Db > Using Relation Table with Zend Framework

Using Relation Table with Zend Framework

intro
This article shows an example of usage of relation table with Zend Framework. You can download the source code of this article from here.
You can see the screens from the demonstration site.

1.Create bootstrap.php and config.ini
Create the file application/bootstrap.php with the following content.
Please modify yourBaseUrl properly.

<?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');

Create the file application/config.ini with the following content.
Please modify database.params.* properly.

[staging]
database.adapter         = pdo_mysql
database.params.host     = localhost
database.params.username = db_user
database.params.password = db_password
database.params.dbname   = db_name

In this article, we will use the following sql.

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.Create Models
Create the file application/models/Projects.php with the following content.

<?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;
    }
 
}

Create the file application/models/ProjectsMembers.php with the following content.

<?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
        )
    );
}

Create the file application/models/forms/ProjectForm.php with the following content.

<?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');
    }
}

Create the file application/models/forms/ProjectMemberSubForm.php with the following content.

<?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.Create Controller
Create the file application/constorllers/ProjectController.php with the following content.
It extends My_Controller_Simple created before.

<?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.Create views
Create the file application/views/scripts/project/list.phtml with the following content.

 
<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; ?>

Create the file application/views/scripts/project/detail.phtml with the following content.

 
<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; ?>

Create the file application/views/scripts/project/form.phtml with the following content.

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

Create the file application/views/scripts/project/finish.phtml with the following content.

 
<h1><?= $this->translate($this->name . '.title.finish.' . $this->action) ?></h1>
 
<a href="<?=$this->url(array('action'=>'list'))?>">
<?= $this->translate('back') ?></a>

Create the file application/views/scripts/common/partList.phtml with the following content.

 
<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.Check
Access the web server and check CRUD process of relation table.

Comments:1

Srinivasan 09-08-05 (Wed) 23:19

Hi,

Any one can confirm that self::CASCADE ondelete , onupdate is working on Zend Framework? or any one can guide me that how can i do that?

Thank you,
K.Srinivasan

Comment Form
Remember personal info

Trackbacks:0

Trackback URL for this entry
http://www.oplabo.com/article/35/trackback
Listed below are links to weblogs that reference
Using Relation Table with Zend Framework from Open Programming Laboratory

Home > Zend_Db > Using Relation Table with Zend Framework

Japanese
Search
Feeds

Return to page top