ZF-38: Zend_Db_Table should allow custom Row objects

Description

http://framework.zend.com/developer/ticket/26

The Zend_Db_Table object should allow configuration of the Row object returned. Currently it's hard coded and it's difficult to create an extension object for the Zend_Db_Table_Row object because of this. A protected property, such as $_rowClassname could be set in any extensions of Zend_Db_Table that would allow a custom Row object to be returned.

This would allow Zend Framework to keep it's goal of being a base for an application, instead of being the application.

Good work so far guys. I'm drooling over this Zend Framework!

Comments

05/06/06 02:40:31: Modified by stephane.crivisier@epitech.net

Here is my way to do this:

Add some static methods in Zend_Db_Table to change the Row object name and a static property to remember it. Change the Zend_Db_Table_Rowset to use Zend_Db_Table::getDefaultRowName() and create a object with that name instead of the Zend_Db_Table_Row object.

Here is the patch:


diff -r /home/stem/www/ZendFramework/trunk/library/Zend/Db/Table.php ./Zend/Db/Table.php
52a59,84
>      * For row object
>      *
>      * @var string
>      */
>     static protected $_defaultRowName = 'Zend_Db_Table_Row';
> 
>     /**
>      * Set the default Row object name
>      *
>      * @param string $name
>      */
>     static public function setDefaultRowName($name)
>     {
>       self::$_defaultRowName = $name;
>     }
>
>     /**
>      * Get the default Row object name
>      * If none have been set by setDefaultRow(), return the default value: 'Zend_Db_Table_Row'
>      *
>      * @return string
>      */
>     static public function getDefaultRowName()
>     {
>       return self::$_defaultRowName;
>     }
> 
>     /**
150d181
<      * @return Zend_Db_Adapter
330c361
<      * @return mixed The row results per the Zend_Db_Adapter fetch mode.
---
>      * @return Zend_Db_Table_Row The row results per the Zend_Db_Adapter fetch mode.
333a365,369
>         return new self::$_defaultRowName(array(
>             'db'    => $this->_db,
>             'table' => $this,
>             'data'  => $this->_fetch('Row', $where, $order, 1),
>         ));
349a386,391
>         return new self::$_defaultRowName(array(
>             'db'    => $this->_db,
>             'table' => $this,
>             'data'  => array_combine($keys, $vals),
> 
>         ));
diff -r /home/stem/www/ZendFramework/trunk/library/Zend/Db/Table/Rowset.php ./Zend/Db/Table/Rowset.php
113c111,112
<             $this->_rows[$this->_pointer] = new Zend_Db_Table_Row(array(
---
>             $name = Zend_Db_Table::getDefaultRow();
>             $this->_rows[$this->_pointer] = new $name(array(

sorry if this one is not valide, I'm not used to use the diff command and it's between svn and 0.1.3 version :( I think it's really simple and the teem smart enougth to do the changes by the hand if necessary 05/11/06 20:44:08: Modified by dev@zayso.org

Fully agree with the notion of being able to specify the row class. Should also be able to specify a class for returning a set of rows.

Disagree with the use of a static variable for the class name. I want different tables to return different types of rows.

I implemented this functionality using inheritiance: abstract class Mine_Db_Table extends Zend_Db_Table {

    protected $_rowClassName = 'Zend_Db_Table_Row'; protected $_rowsetClassName = 'Zend_Db_Table_Rowset';

class PersonTable? extends Mine_Db_Table {

    protected $_rowClassName = 'PersonRow'; protected $_rowsetClassName = 'PersonRows';

Seems to work well.

Now that 0.1.5 has been released I'm hoping that we can get some idea if some of these suggested enhancements will be added to the frame work. There has been at least two email threads on this enhancement which sort of indicates that people might want it. Or maybe DB_Table is to be replaced by some sort of Active Record system?

a possible patch for Table.php

about proposal : http://framework.zend.com/wiki/display/…

I believe there are some important bugs (listed in our issue tracker) relating to the Zend_Db* classes that should be resolved before adding significant new functionality.

Currently, I think many would like a more Active Record like abstraction in the ZF, but want to avoid having to generate stub class code for every table in the DB, maintain complex logic/structure in configuration files, or create unique classes for every table participating in the group of tables mapped by these abstractions to an object-oriented API.

Such desires seem to imply reflection on database schemas using special case code for each database, caching the results efficiently, and algorithmically mapping data in the tables to object accessors/properties without precluding the interjection of subclasses to compute more complex object properties from available data. Reflection would require some degree of schema design-by-convention. Query aggregation, Unit of Work, lazy loading, and effective modelling of common object relationships and aggregations pose thorny problems for algorithmic mappings, especially when considering a single implementation that addresses all these concerns.

Hum... I understand that you want to close bugs before adding significant new functionality but IMHO : - it's a little patch (between 10 and 20 lines with comments included on 2 files) - there is no API break at all (because with default values, it's just work as now) - there is no new method (just two protected properties with good default values)

Even the manual won't have to be modified (if you don't want to describe the new features) !

IMHO, it's a very constructive and pragmatic patch : - People who wants a complete ORM mapping will be able to build a system upon Zend_Db_Table - People who prefers a lite system will be able to continue with current features (without extra code because the current way will continue to work without modification at all)

Of course, the complete and lite solution as you describe is not for tomorrow and will need a lot of reflection and work. That's why I think this patch (which is only a first step to show the path) has to be applied ASAP.

Regards

It'd be a better idea to use a protected function to get the return type instead of a protected property. By using a function, users could overload the function and return different types based on data from the result set, thus allowing Zend_Db_Table to be used with single table inheritance setups.

Changing fix version to 0.8.0.

Recategorize as Zend_Db_Table component.

Bill,

When you say: "Changing fix version to 0.8.0.", do you mean that this will be fixed in 0.9.0?

Or, to put it another way. How likely is this bug likely to be fixed for ZF 1.0?

Regards,

Rob...

During the ZF 0.8 iteration, I fixed 37 bugs in Zend_Db, but I concentrated on Zend_Db_Adapter and Zend_Db_Select issues.

I also wrote unit tests for Zend_Db_Table, Zend_Db_Table_Row, and Zend_Db_Table_Rowset, to raise unit test code coverage from 0% to 100% on those classes. I felt this was prerequisite to working on the classes.

Now that we are in the ZF 0.9 iteration, I plan to address many issues in Zend_Db_Table and its companions.

As of revision 3995, Zend_Db_Table_Row is now Zend_Db_Table_Row_Abstract, and likewise Zend_Db_Table_Rowset is now Zend_Db_Table_Rowset_Abstract.

The Row and Rowset classes can be extended. The Zend_Db_Table recognizes keys in its options array 'rowClass' and 'rowsetClass', which name the user's choice for their custom Row and Rowset classes.