PhpRiot
Become Zend Certified

Prepare for the ZCE exam using our quizzes (web or iPad/iPhone). More info...


When you're ready get 7.5% off your exam voucher using voucher CJQNOV23 at the Zend Store

Customizing and Extending a Table Class

Using Custom Row or Rowset Classes

By default, methods of the Table class return a Rowset in instances of the concrete class Zend_Db_Table_Rowset, and Rowsets contain a collection of instances of the concrete class Zend_Db_Table_Row You can specify an alternative class to use for either of these, but they must be classes that extend Zend_Db_Table_Rowset_Abstract and Zend_Db_Table_Row_Abstract, respectively.

You can specify Row and Rowset classes using the Table constructor's options array, in keys 'rowClass' and 'rowsetClass' respectively. Specify the names of the classes using strings.

Example 297. Example of specifying the Row and Rowset classes

<?php
class My_Row extends Zend_Db_Table_Row_Abstract
{
    ...
}

class 
My_Rowset extends Zend_Db_Table_Rowset_Abstract
{
    ...
}

$table = new Bugs(
    array(
        
'rowClass'    => 'My_Row',
        
'rowsetClass' => 'My_Rowset'
    
)
);

$where $table->getAdapter()->quoteInto('bug_status = ?''NEW')

// Returns an object of type My_Rowset,
// containing an array of objects of type My_Row.
$rows $table->fetchAll($where);

You can change the classes by specifying them with the setRowClass() and setRowsetClass() methods. This applies to rows and rowsets created subsequently; it does not change the class of any row or rowset objects you have created previously.

Example 298. Example of changing the Row and Rowset classes

<?php
$table 
= new Bugs();

$where $table->getAdapter()->quoteInto('bug_status = ?''NEW')

// Returns an object of type Zend_Db_Table_Rowset
// containing an array of objects of type Zend_Db_Table_Row.
$rowsStandard $table->fetchAll($where);

$table->setRowClass('My_Row');
$table->setRowsetClass('My_Rowset');

// Returns an object of type My_Rowset,
// containing an array of objects of type My_Row.
$rowsCustom $table->fetchAll($where);

// The $rowsStandard object still exists, and it is unchanged.

For more information on the Row and Rowset classes, see this chapter and this one.

Defining Custom Logic for Insert, Update, and Delete

You can override the insert() and update() methods in your Table class. This gives you the opportunity to implement custom code that is executed before performing the database operation. Be sure to call the parent class method when you are done.

Example 299. Custom logic to manage timestamps

<?php
class Bugs extends Zend_Db_Table_Abstract
{
    protected 
$_name 'bugs';

    public function 
insert(array $data)
    {
        
// add a timestamp
        
if (empty($data['created_on'])) {
            
$data['created_on'] = time();
        }
        return 
parent::insert($data);
    }

    public function 
update(array $data$where)
    {
        
// add a timestamp
        
if (empty($data['updated_on'])) {
            
$data['updated_on'] = time();
        }
        return 
parent::update($data$where);
    }
}

You can also override the delete() method.

Define Custom Search Methods in Zend_Db_Table

You can implement custom query methods in your Table class, if you have frequent need to do queries against this table with specific criteria. Most queries can be written using fetchAll(), but this requires that you duplicate code to form the query conditions if you need to run the query in several places in your application. Therefore it can be convenient to implement a method in the Table class to perform frequently-used queries against this table.

Example 300. Custom method to find bugs by status

<?php
class Bugs extends Zend_Db_Table_Abstract
{
    protected 
$_name 'bugs';

    public function 
findByStatus($status)
    {
        
$where $this->getAdapter()->quoteInto('bug_status = ?'$status);
        return 
$this->fetchAll($where'bug_id');
    }
}

Define Inflection in Zend_Db_Table

Some people prefer that the table class name match a table name in the RDBMS by using a string transformation called inflection.

For example, if your table class name is "BugsProducts", it would match the physical table in the database called "bugs_products", if you omit the explicit declaration of the $_name class property. In this inflection mapping, the class name spelled in "CamelCase" format would be transformed to lower case, and words are separated with an underscore.

You can specify the database table name independently from the class name by declaring the table name with the $_name class property in each of your table classes.

Zend_Db_Table_Abstract performs no inflection to map the class name to the table name. If you omit the declaration of $_name in your table class, the class maps to a database table that matches the spelling of the class name exactly.

It is inappropriate to transform identifiers from the database, because this can lead to ambiguity or make some identifiers inaccessible. Using the SQL identifiers exactly as they appear in the database makes Zend_Db_Table_Abstract both simpler and more flexible.

If you prefer to use inflection, then you must implement the transformation yourself, by overriding the _setupTableName() method in your Table classes. One way to do this is to define an abstract class that extends Zend_Db_Table_Abstract, and then the rest of your tables extend your new abstract class.

Example 301. Example of an abstract table class that implements inflection

<?php
abstract class MyAbstractTable extends Zend_Db_Table_Abstract
{
    protected function 
_setupTableName()
    {
        if (!
$this->_name) {
            
$this->_name myCustomInflector(get_class($this));
        }
        
parent::_setupTableName();
    }
}

class 
BugsProducts extends MyAbstractTable
{
}

You are responsible for writing the functions to perform inflection transformation. Zend Framework does not provide such a function.

Zend Framework