views:

455

answers:

4

I am unable to define referential integrity relationship using Zend Frameworks table relationships as documented in the manual.

I have exhausted every possible configuration (so it seems), and now am facing the prospect of developing the application without being able to use cascading deletions, which is undesirable.

Can anyone see what is wrong or offer any suggestions?

My project is setup using the new ZF 1.8.3 recommended method, with datamappers, and I wonder if this is a reason why I am unable to replicate the behavior as described in the reference guide. Does anyone have any experience of this problem?

Here are the relevant parts of the classes:

application/models/UsersMapper.php

class Default_Model_UsersMapper {
    public function deleteUser($id, Default_Model_Users $users){

 $usersTable = new Default_Model_DbTable_Users();  
 $usersRowset = $usersTable->find( $id ); 
 $userToDelete = $usersRowset->current();  
 $userToDelete->delete();

}

application/models/DbTable/Users.php

class Default_Model_DbTable_Users extends Zend_Db_Table_Abstract
{
/**
 * @var string Name of the database table
 */
protected $_name = 'users';

/**
 * @desc  reference map 
 * 
 */
 protected $_referenceMap = array(
    'Comment' => array(
    'columns'   => array('user_id'),
     'refTableClass' =>  'Comment',
     'refColumns' =>  array('id'),
     'onDelete'  =>  self::CASCADE
    )
);

}

application/models/CommentMapper.php

… and the related table defined by the class:

Comment.php

class Default_Model_DbTable_Comment extends Zend_Db_Table_Abstract
{
/**
 * @var string Name of the database table
 */
protected $_name = 'comment';

    /**
 * @desc Defining referential integrity here since we are using MyISAM
 * Dependent tables are referred via the class name. 
 */
protected $_dependentTables = array('Users');
}
A: 

You want to delete a user and expect all comments that user made to be deleted as well?

Then your layout is wrong.

The 'users' table is the higher ranking table and therefore needs the

protected $_dependentTables = array('Comment');

Sidenote: should be users and comments since these are tables containing many users and comments. what if you want to create row objects? how will you name them?

And the 'comments' table needs the

protected $_referenceMap = array(
    'User' => array(
        'columns'       =>  array('id'),
        'refTableClass' =>  'User',
        'refColumns'    =>  array('user_id'),
        'onDelete'      =>  self::CASCADE
    )
);

And maybe you need to have InnoDB tables.

tharkun
He's using a modular application structure with a very common naming format, that follows the Zend coding standard. He's also not using his Table Data Gateway's as models, in favor of a Data Mapper implementation. That's why he named his classes as such.
hobodave
I see, deleted the respective part.
tharkun
the rest is still valid.
tharkun
Thanks a lot for the feedback. So there is no reason the Data Mapping implementation should stop this from working? I think I have tried it with the users table as the primary table, but I will try again and make tweaks and trials and errors from that position. Thanks again. This is my 1st time here and I am very impressed so far with this site.
Daniel Higgins
No, the Data Mapping shouldn't stop this from working.
tharkun
InnoDB tables shouldn't be required - ZF implements a software solution for triggers
David Caunt
A: 

Ohhhh, I see it now. Your classes are named Default_Model_DbTable_Xxx, yet you refer to them as Xxx in your classes. Do the changes tharkun suggested and change your classnames to be valid:

e.g.

protected $_dependentTables = array('Comment');

and

'refTableClass' =>      'User',

becomes

protected $_dependentTables = array('Default_Model_DbTable_Comment');

and

'refTableClass' => 'Default_Model_DbTable_User'
hobodave
+1  A: 

Thanks for spotting the mistake in the class definitions.

My problem getting Zend Framework to provide a DRI layer has become narrowed and can now be summarized as such.

Using these class definitions I am able to delete the user but not the related comment through my local UserController "public/users/delete/userId/22"

    class Default_Model_DbTable_Comment extends Zend_Db_Table_Abstract
    {
        /**
         * @var string Name of the database table
         */
        protected $_name = 'comment';

        /**
         * @desc  reference map 
         * 
         * Rows in the comment table are to be automatically deleted if the row in the 
     * User table to which they refer is deleted
     *    
     */
     protected $_referenceMap = array(
        'User' => array(
         'columns'   => 'user_id',   // the foreign key(s)
      'refTableClass' => 'Default_Model_DbTable_Users',
         'refColumns' =>  'id',
         'onDelete'  =>  self::CASCADE,
        )
    );

}
class Default_Model_DbTable_Users extends Zend_Db_Table_Abstract
{
    /**
     * @var string Name of the database table
     */
    protected $_name = 'users';


     /**
     * @desc Defining referential integrity here since we are using MyISAM
     * Dependent tables are referred via the class name. 
     */
    protected $_dependentTables = 'Default_Model_DbTable_Comment';



}
Daniel Higgins
A: 

This is kind of stupid... And what about class autoload?

Giez

related questions