ZF-6461: Split Zend_Db_Table_Row_Abstract::findDependentRowset to allow direct access to the Zend_Db_Table_Select object
Description
Zend_Db_Table_Row_Abstract::findDependentRowset find the child rows for a particular table for a Zend_Db_Table_Row object.
It does this by building a Zend_Db_Table_Select object and then calling Zend_Db_Table_Abstract::fetchAll to return the rows:
public function findDependentRowset($dependentTable, $ruleKey = null, Zend_Db_Table_Select $select = null)
{
$db = $this->_getTable()->getAdapter();
Build Zend_Db_Table_Select object $select
return $dependentTable->fetchAll($select);
}
Sometimes it is more useful to have direct access to the $select object than it is to the rowset. My use case is using Zend_Paginator to display a paginated list of child rows in a master-detail screen. This works best (for us at least) if we have a Zend_Db_Table_Select representing the whole rowset, and we then allow Zend_Paginator to change the offset and limit clauses as required to bring back the required rows.
This is easily accomplished if we split the existing findDependentRowset into a method to build the $select and a separate method to return the rowset.
The new getDependentSelect is identical to the existing findDependentRowset except for the last line which returns the $select instead of a rowset:
/**
* Generate a select statement to query a dependent table to retrieve rows matching the current row.
*
* @param string|Zend_Db_Table_Abstract $dependentTable
* @param string OPTIONAL $ruleKey
* @param Zend_Db_Table_Select OPTIONAL $select
* @return Zend_Db_Table_Select Query result from $dependentTable
* @throws Zend_Db_Table_Row_Exception If $dependentTable is not a table or is not loadable.
*/
public function getDependentSelect($dependentTable, $ruleKey = null, Zend_Db_Table_Select $select = null)
{
$db = $this->_getTable()->getAdapter();
if (is_string($dependentTable)) {
try {
@Zend_Loader::loadClass($dependentTable);
} catch (Zend_Exception $e) {
require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception($e->getMessage());
}
$dependentTable = new $dependentTable(array('db' => $db));
}
if (! $dependentTable instanceof Zend_Db_Table_Abstract) {
$type = gettype($dependentTable);
if ($type == 'object') {
$type = get_class($dependentTable);
}
require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Dependent table must be a Zend_Db_Table_Abstract, but it is $type");
}
if ($select === null) {
$select = $dependentTable->select();
} else {
$select->setTable($dependentTable);
}
$map = $this->_prepareReference($dependentTable, $this->_getTable(), $ruleKey);
for ($i = 0; $i < count($map[Zend_Db_Table_Abstract::COLUMNS]); ++$i) {
$parentColumnName = $db->foldCase($map[Zend_Db_Table_Abstract::REF_COLUMNS][$i]);
$value = $this->_data[$parentColumnName];
// Use adapter from dependent table to ensure correct query construction
$dependentDb = $dependentTable->getAdapter();
$dependentColumnName = $dependentDb->foldCase($map[Zend_Db_Table_Abstract::COLUMNS][$i]);
$dependentColumn = $dependentDb->quoteIdentifier($dependentColumnName, true);
$dependentInfo = $dependentTable->info();
$type = $dependentInfo[Zend_Db_Table_Abstract::METADATA][$dependentColumnName]['DATA_TYPE'];
$select->where("$dependentColumn = ?", $value, $type);
}
return $select;
}
findDependentRowset now becomes a call to getDependentSelect:
/**
* Query a dependent table to retrieve rows matching the current row.
*
* @param string|Zend_Db_Table_Abstract $dependentTable
* @param string OPTIONAL $ruleKey
* @param Zend_Db_Table_Select OPTIONAL $select
* @return Zend_Db_Table_Rowset_Abstract Query result from $dependentTable
* @throws Zend_Db_Table_Row_Exception If $dependentTable is not a table or is not loadable.
*/
public function findDependentRowset($dependentTable, $ruleKey = null, Zend_Db_Table_Select $select = null)
{
$select = $this->getDependentSelect($dependentTable, $ruleKey, $select);
return $select->getTable()->fetchAll($select);
}
This allows my use case to work easily:
// Create the child paginator
$select = $row->getDependentSelect($child);
$page = $this->_request->getParam('page');
$paginator = Zend_Paginator::factory($select, 'DbTableSelect');
$paginator->setCurrentPageNumber($page);
$this->view->childPaginator = $paginator;
Comments
Posted by Jurrien Stutterheim (norm2782) on 2009-07-29T08:27:04.000+0000
Might be useful to refactor the many-to-many and parent-row support as well.
Posted by Adam Lundrigan (adamlundrigan) on 2012-05-29T02:31:16.000+0000
Duplicate of ZF-4692