Zend_DB_Table: delete() won't delete any row in dependent tables

9 messages Options
Embed this post
Permalink
Thomas D.-2

Zend_DB_Table: delete() won't delete any row in dependent tables

Reply Threaded More More options
Print post
Permalink
Hi,

I have two tables, drivers and cars.
Each driver in drivers has his cars in cars.

When I delete a driver, his cars should also be deleted in cars.

I defined two classes:

class Drivers extends Zend_Db_Table_Abstract
{
    [...]
    protected $_dependentTables = array(
        'Cars'
    );
}

class Cars extends Zend_Db_Table_Abstract
{
    [...]
    protected $_referenceMap = array(
        'Pages' => array(
            'columns'       => array('driver_id'),
            'refTableClass' => 'Drivers',
            'refColumns'    => 'id',
            'onDelete'      => self::CASCADE
        )
    );
}

When I run

$myTable = new Drivers();
$driversRowset = $myTable ->find(1278);
$driver = $driversRowset->current();

$driver->delete();

The row with id 1278 in my drivers table will be deleted and also all rows
in cars, where driver_id = 1278. Everything is working as expected.

Now I want to add a method to my drivers Zend_Db_Table class, which will
delete a driver and do something else:

class Drivers extends Zend_Db_Table_Abstract
{
    [...]
    public function doSth($id)
    {
        $where = $this->_db->quoteInto('id = ?', $id, Zend_Db::INT_TYPE);
        $this->delete($where);

        // do my other stuff
        [...]
    }
}

My problem is, that when I call $driverTable->doSth(1278), the row in the
driver's table will be deleted, but it won't delete any rows in cars.

Did I miss something?


--
Regards,
Thomas


Andrew Ballard

Re: Zend_DB_Table: delete() won't delete any row in dependent tables

Reply Threaded More More options
Print post
Permalink
On Tue, Jun 30, 2009 at 12:18 AM, Thomas D.<[hidden email]> wrote:

> Hi,
>
> I have two tables, drivers and cars.
> Each driver in drivers has his cars in cars.
>
> When I delete a driver, his cars should also be deleted in cars.
>
> I defined two classes:
>
> class Drivers extends Zend_Db_Table_Abstract
> {
>    [...]
>    protected $_dependentTables = array(
>        'Cars'
>    );
> }
>
> class Cars extends Zend_Db_Table_Abstract
> {
>    [...]
>    protected $_referenceMap = array(
>        'Pages' => array(
>            'columns'       => array('driver_id'),
>            'refTableClass' => 'Drivers',
>            'refColumns'    => 'id',
>            'onDelete'      => self::CASCADE
>        )
>    );
> }
>
> When I run
>
> $myTable = new Drivers();
> $driversRowset = $myTable ->find(1278);
> $driver = $driversRowset->current();
>
> $driver->delete();
>
> The row with id 1278 in my drivers table will be deleted and also all rows
> in cars, where driver_id = 1278. Everything is working as expected.
>
> Now I want to add a method to my drivers Zend_Db_Table class, which will
> delete a driver and do something else:
>
> class Drivers extends Zend_Db_Table_Abstract
> {
>    [...]
>    public function doSth($id)
>    {
>        $where = $this->_db->quoteInto('id = ?', $id, Zend_Db::INT_TYPE);
>        $this->delete($where);
>
>        // do my other stuff
>        [...]
>    }
> }
>
> My problem is, that when I call $driverTable->doSth(1278), the row in the
> driver's table will be deleted, but it won't delete any rows in cars.
>
> Did I miss something?
>
>
> --
> Regards,
> Thomas
>
>
>

You are changing the syntax between the two examples. In the first,
you are calling finding a specific row and
Zend_Db_Table_Row_Abstract::delete() on that row, which is what is
shown in the documentation. This function scans the dependent tables
and deletes all dependent rows.

In the second, you are calling the Zend_Db_Table_Abstract::delete()
method, which simply calls delete() on the database adapter.

It looks like you just need to change your doSth() method to this:

class Drivers extends Zend_Db_Table_Abstract
{
   [...]
   public function doSth($id)
   {
       $driversRowset = $this->find($id);
       $driver = $driversRowset->current();

       $driver->delete();

       // do my other stuff
       [...]
   }
}

Andrew
Thomas D.-2

RE: Zend_DB_Table: delete() won't delete any row in dependent tables

Reply Threaded More More options
Print post
Permalink
Hi,

Andrew Ballard wrote:

> You are changing the syntax between the two examples. In the first,
> you are calling finding a specific row and
> Zend_Db_Table_Row_Abstract::delete() on that row, which is what is
> shown in the documentation. This function scans the dependent tables
> and deletes all dependent rows.
>
> In the second, you are calling the Zend_Db_Table_Abstract::delete()
> method, which simply calls delete() on the database adapter.
>
> It looks like you just need to change your doSth() method to this:
>
> class Drivers extends Zend_Db_Table_Abstract
> {
>    [...]
>    public function doSth($id)
>    {
>        $driversRowset = $this->find($id);
>        $driver = $driversRowset->current();
>
>        $driver->delete();
>
>        // do my other stuff
>        [...]
>    }
> }

You are right. The delete() method, which will delete rows in dependent tables is the delete() method of the Zend_Db_Table_Row, but I was using the delete() method of Zend_Db_Table.

Your solution is working fine.

Thank you Andrew.


--
Regards,
Thomas


Ben Scholzen 'DASPRiD'

Re: Zend_DB_Table: delete() won't delete any row in dependent tables

Reply Threaded More More options
Print post
Permalink
In reply to this post by Thomas D.-2
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

You should probably take a look at Foreign Keys and Cascading in your
database's manual.
...................................
:  ___   _   ___ ___ ___ _ ___    :
: |   \ /_\ / __| _ \ _ (_)   \   :
: | |) / _ \\__ \  _/   / | |) |  :
: |___/_/:\_\___/_| |_|_\_|___/   :
:........:........................:
: Web    : http://www.dasprids.de :
: E-mail : [hidden email]       :
: Jabber : [hidden email]     :
: ICQ    : 105677955              :
:........:........................:


Thomas D. schrieb:

> Hi,
>
> I have two tables, drivers and cars.
> Each driver in drivers has his cars in cars.
>
> When I delete a driver, his cars should also be deleted in cars.
>
> I defined two classes:
>
> class Drivers extends Zend_Db_Table_Abstract
> {
>     [...]
>     protected $_dependentTables = array(
>         'Cars'
>     );
> }
>
> class Cars extends Zend_Db_Table_Abstract
> {
>     [...]
>     protected $_referenceMap = array(
>         'Pages' => array(
>             'columns'       => array('driver_id'),
>             'refTableClass' => 'Drivers',
>             'refColumns'    => 'id',
>             'onDelete'      => self::CASCADE
>         )
>     );
> }
>
> When I run
>
> $myTable = new Drivers();
> $driversRowset = $myTable ->find(1278);
> $driver = $driversRowset->current();
>
> $driver->delete();
>
> The row with id 1278 in my drivers table will be deleted and also all rows
> in cars, where driver_id = 1278. Everything is working as expected.
>
> Now I want to add a method to my drivers Zend_Db_Table class, which will
> delete a driver and do something else:
>
> class Drivers extends Zend_Db_Table_Abstract
> {
>     [...]
>     public function doSth($id)
>     {
>         $where = $this->_db->quoteInto('id = ?', $id, Zend_Db::INT_TYPE);
>         $this->delete($where);
>
>         // do my other stuff
>         [...]
>     }
> }
>
> My problem is, that when I call $driverTable->doSth(1278), the row in the
> driver's table will be deleted, but it won't delete any rows in cars.
>
> Did I miss something?
>
>
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkpKI5cACgkQ0HfT5Ws789B2ogCgiElFfBypyBWKPD3l5v4dqa1k
wkkAoIe7o8TUAhNCBFXRdgrV1T4ZUmUN
=mSbg
-----END PGP SIGNATURE-----
Thomas D.-2

RE: Zend_DB_Table: delete() won't delete any row in dependent tables

Reply Threaded More More options
Print post
Permalink
Hi,

Ben Scholzen 'DASPRiD' wrote:
> You should probably take a look at Foreign Keys and Cascading in your
> database's manual.

As I have written in a reply for Andrew, the database I am working with uses
the MyISAM engine, which don't support foreign keys.

Converting the engine to InnoDB is currently not an option. This would
require further testing of other - old - modules.


--
Regards,
Thomas


Andrew Ballard

Re: Zend_DB_Table: delete() won't delete any row in dependent tables

Reply Threaded More More options
Print post
Permalink
In reply to this post by Thomas D.-2
On Tue, Jun 30, 2009 at 12:18 AM, Thomas D.<[hidden email]> wrote:

> Hi,
>
> I have two tables, drivers and cars.
> Each driver in drivers has his cars in cars.
>
> When I delete a driver, his cars should also be deleted in cars.
>
> I defined two classes:
>
> class Drivers extends Zend_Db_Table_Abstract
> {
>    [...]
>    protected $_dependentTables = array(
>        'Cars'
>    );
> }
>
> class Cars extends Zend_Db_Table_Abstract
> {
>    [...]
>    protected $_referenceMap = array(
>        'Pages' => array(
>            'columns'       => array('driver_id'),
>            'refTableClass' => 'Drivers',
>            'refColumns'    => 'id',
>            'onDelete'      => self::CASCADE
>        )
>    );
> }
>
> When I run
>
> $myTable = new Drivers();
> $driversRowset = $myTable ->find(1278);
> $driver = $driversRowset->current();
>
> $driver->delete();
>
> The row with id 1278 in my drivers table will be deleted and also all rows
> in cars, where driver_id = 1278. Everything is working as expected.
>
> Now I want to add a method to my drivers Zend_Db_Table class, which will
> delete a driver and do something else:
>
> class Drivers extends Zend_Db_Table_Abstract
> {
>    [...]
>    public function doSth($id)
>    {
>        $where = $this->_db->quoteInto('id = ?', $id, Zend_Db::INT_TYPE);
>        $this->delete($where);
>
>        // do my other stuff
>        [...]
>    }
> }
>
> My problem is, that when I call $driverTable->doSth(1278), the row in the
> driver's table will be deleted, but it won't delete any rows in cars.
>
> Did I miss something?
>
>
> --
> Regards,
> Thomas
>
>
>

Is referential integrity not an option?

Andrew
Thomas D.-2

RE: Zend_DB_Table: delete() won't delete any row in dependent tables

Reply Threaded More More options
Print post
Permalink
Hi,

thank you for your reply.

Andrew Ballard wrote:
> Is referential integrity not an option?

No, the tables I am working with are part of a MyISAM database of an existing, not fully Zend_Framework based application (I am working on the first Zend_Framework based module).

Converting the whole table to InnoDB isn't currently an option.


--
Regards,
Thomas


Carlton Gibson-2

Re: Zend_DB_Table: delete() won't delete any row in dependent tables

Reply Threaded More More options
Print post
Permalink
In reply to this post by Andrew Ballard
On Tue, Jun 30, 2009 at 12:18 AM, Thomas D.<[hidden email]>  
wrote:

> Hi,
>
> I have two tables, drivers and cars.
> Each driver in drivers has his cars in cars.
>
> When I delete a driver, his cars should also be deleted in cars.
>
> I defined two classes:
>
> class Drivers extends Zend_Db_Table_Abstract
> {
>    [...]
>    protected $_dependentTables = array(
>        'Cars'
>    );
> }
>
> class Cars extends Zend_Db_Table_Abstract
> {
>    [...]
>    protected $_referenceMap = array(
>        'Pages' => array(
>            'columns'       => array('driver_id'),
>            'refTableClass' => 'Drivers',
>            'refColumns'    => 'id',
>            'onDelete'      => self::CASCADE
>        )
>    );
> }
>
> When I run
>
> $myTable = new Drivers();
> $driversRowset = $myTable ->find(1278);
> $driver = $driversRowset->current();
>
> $driver->delete();
>
> The row with id 1278 in my drivers table will be deleted and also  
> all rows
> in cars, where driver_id = 1278. Everything is working as expected.
>
> Now I want to add a method to my drivers Zend_Db_Table class, which  
> will
> delete a driver and do something else:
>
> class Drivers extends Zend_Db_Table_Abstract
> {
>    [...]
>    public function doSth($id)
>    {
>        $where = $this->_db->quoteInto('id = ?', $id,  
> Zend_Db::INT_TYPE);
>        $this->delete($where);
>
>        // do my other stuff
>        [...]
>    }
> }
>
> My problem is, that when I call $driverTable->doSth(1278), the row  
> in the
> driver's table will be deleted, but it won't delete any rows in cars.
>
> Did I miss something?


Yes. The cascading write options ONLY work via the Row object.

In your method doSth you are using the table's delete() method, which  
does not enforce the cascade specified in the $_referenceMap array.

In the example previously you are using the row object's delete().  
This does enforce the cascade.

If you change your doSth() method to use fetchRow() and then call  
delete on that all should work as you intend.

I hope this helps. I have been caught out by this one myself and  
(still) am not sure WHY the table's delete() method doesn't behave as  
you expected.

Regards,
Carlton
Thomas D.-2

RE: Zend_DB_Table: delete() won't delete any row in dependent tables

Reply Threaded More More options
Print post
Permalink
Hi,

Carlton Gibson wrote:
> > My problem is, that when I call $driverTable->doSth(1278), the row
> > in the driver's table will be deleted, but it won't delete any rows
> > in cars.
> >
> > Did I miss something?
>
> Yes. The cascading write options ONLY work via the Row object.

Thank you, too. That was the problem.


--
Regards,
Thomas