Second Party.
We wants more!!! I and Milfont need the inheritance with 2 tables. An example is the table Person and Developer. A Developer is a Person and in ORM he need have fullname, but this data belongs to table Person. :D
tables:
+------------------+ +--------------+
|Person | |Developer |
+------------------+ +--------------+
|id_person int (PK)|--+ |id_developer |
+------------------+ | +--------------+
|fullname varchar | <>|id_person (FK)|
+------------------+ +--------------+
|language |
+--------------+
I wanna a code like follow work:
<?php
$devModel = new Developer(); //Model class extended Zend_Db_Table_Abstract and $_name="Developer"
$dev = $devModel->find(1)->current();
$dev->fullname = "full name test";
$dev->save(); // here the fullname will save in Person Table
?>
So I modify the Zend_Db_Table* classes.
The first step was choice the way and I choice create a attribute call _father(protected) in each instance of Row and a attribute call _fatherRule(protected) in table class. This have the name of rule of _referenceMap. In my choise the class Developer extends class Person, but can be implemented in difence way. I modify this fallow methods to call the rigth method in _father if the attribute not exist in current instance.
Zend_Db_Table_Abstract:
/**
* @var string
*/
protected $_fatherRule = "";
public function getFatherRule()
{
return $this->_fatherRule;
}
Zend_Db_Table_Row_Abstract
/**
* Object father
*
* @var Zend_Db_Table_Row_Abstract
*/
protected $_father = null;
/**
* Initialize object
*
* Called from {@link __construct()} as final step of object instantiation.
*
* @return void
*/
public function init()
{
parent::init();
if ($this->_table->getFatherRule())
{
$this->_father = $this->findParentRow(get_parent_class($this->_table),$this->_table->getFatherRule());
}
$this->_columnMap = $this->_table->getColumnMap();
}
/**
* Retrieve row field value
*
* @param string $columnName The user-specified column name.
* @return string The corresponding column value.
* @throws Zend_Db_Table_Row_Exception if the $columnName is not a column in the row.
*/
public function __get($columnName)
{
$columnName = $this->_transformColumn($columnName);
if (!array_key_exists($columnName, $this->_data)) {
if ($this->_father)
{
return $this->_father->$columnName;
}
else
{
require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Specified column \"$columnName\" is not in the row");
}
}
else
{
return $this->_data[$columnName];
}
}
/**
* Set row field value
*
* @param string $columnName The column key.
* @param mixed $value The value for the property.
* @return void
* @throws Zend_Db_Table_Row_Exception
*/
public function __set($columnName, $value)
{
$columnName = $this->_transformColumn($columnName);
if (!array_key_exists($columnName, $this->_data)) {
if ($this->_father)
{
$this->_father->$columnName=$value;
}
else
{
require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Specified column \"$columnName\" is not in the row");
}
}
$this->_data[$columnName] = $value;
$this->_modifiedFields[$columnName] = true;
}
/**
* Test existence of row field
*
* @param string $columnName The column key.
* @return boolean
*/
public function __isset($columnName)
{
$columnName = $this->_transformColumn($columnName);
if (array_key_exists($columnName, $this->_data))
{
return true;
}
else if ($this->_father)
{
return $this->_father->__isset($columnName);
}
else
{
return false;
}
}
/**
* Store table, primary key and data in serialized object
*
* @return array
*/
public function __sleep()
{
return array('_tableClass', '_primary', '_data', '_cleanData', '_readOnly' ,'_modifiedFields','_father');
}
/**
* Saves the properties to the database.
*
* This performs an intelligent insert/update, and reloads the
* properties with fresh data from the table on success.
*
* @return mixed The primary key value(s), as an associative array if the
* key is compound, or a scalar if the key is single-column.
*/
public function save()
{
parent::save();
if ($this->_father)
{
$this->_father->save();
}
}
/**
* Query a parent table to retrieve the single row matching the current row.
*
* @param string|Zend_Db_Table_Abstract $parentTable
* @param string OPTIONAL $ruleKey
* @return Zend_Db_Table_Row_Abstract Query result from $parentTable
* @throws Zend_Db_Table_Row_Exception If $parentTable is not a table or is not loadable.
*/
public function findParentRow($parentTable, $ruleKey = null, Zend_Db_Table_Select $select = null)
{
$db = $this->_getTable()->getAdapter();
if (is_string($parentTable)) {
try {
@Zend_Loader::loadClass($parentTable);
} catch (Zend_Exception $e) {
require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception($e->getMessage());
}
$parentTable = new $parentTable(array('db' => $db));
}
if (! $parentTable instanceof Zend_Db_Table_Abstract) {
$type = gettype($parentTable);
if ($type == 'object') {
$type = get_class($parentTable);
}
require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Parent table must be a Zend_Db_Table_Abstract, but it is $type");
}
try {
$map = $this->_prepareReference($this->_getTable(), $parentTable, $ruleKey);
if ($select === null) {
$select = $parentTable->select();
} else {
$select->setTable($parentTable);
}
for ($i = 0; $i < count($map[Zend_Db_Table_Abstract::COLUMNS]); ++$i) {
$dependentColumnName = $db->foldCase($map[Zend_Db_Table_Abstract::COLUMNS][$i]);
$value = $this->_data[$dependentColumnName];
// Use adapter from parent table to ensure correct query construction
$parentDb = $parentTable->getAdapter();
$parentColumnName = $parentDb->foldCase($map[Zend_Db_Table_Abstract::REF_COLUMNS][$i]);
$parentColumn = $parentDb->quoteIdentifier($parentColumnName, true);
$parentInfo = $parentTable->info();
$type = $parentInfo[Zend_Db_Table_Abstract::METADATA][$parentColumnName]['DATA_TYPE'];
$select->where("$parentColumn = ?", $value, $type);
}
return $parentTable->fetchRow($select);
}
catch (Zend_Db_Table_Exception $e)
{
if ($this->_father)
{
return $this->_father->findParentRow($parentTable,$ruleKey,$select);
}
else
{
throw $e;
}
}
}
I can implement Zend_Db_Table_Row_Abstract::findParentRow,but lack implement the Zend_Db_Table_Row_Abstract::findDependentRowset and Zend_Db_Table_Row_Abstract::findManyToManyRowset.
--
Fernando Chucre - LPIC-1
http://www.horizontesdigitais.com
We wants more!!! I and Milfont need the inheritance with 2 tables. An example is the table Person and Developer. A Developer is a Person and in ORM he need have fullname, but this data belongs to table Person. :D
tables:
+------------------+ +--------------+
|Person | |Developer |
+------------------+ +--------------+
|id_person int (PK)|--+ |id_developer |
+------------------+ | +--------------+
|fullname varchar | <>|id_person (FK)|
+------------------+ +--------------+
|language |
+--------------+
I wanna a code like follow work:
<?php
$devModel = new Developer(); //Model class extended Zend_Db_Table_Abstract and $_name="Developer"
$dev = $devModel->find(1)->current();
$dev->fullname = "full name test";
$dev->save(); // here the fullname will save in Person Table
?>
So I modify the Zend_Db_Table* classes.
The first step was choice the way and I choice create a attribute call _father(protected) in each instance of Row and a attribute call _fatherRule(protected) in table class. This have the name of rule of _referenceMap. In my choise the class Developer extends class Person, but can be implemented in difence way. I modify this fallow methods to call the rigth method in _father if the attribute not exist in current instance.
Zend_Db_Table_Abstract:
/**
* @var string
*/
protected $_fatherRule = "";
public function getFatherRule()
{
return $this->_fatherRule;
}
Zend_Db_Table_Row_Abstract
/**
* Object father
*
* @var Zend_Db_Table_Row_Abstract
*/
protected $_father = null;
/**
* Initialize object
*
* Called from {@link __construct()} as final step of object instantiation.
*
* @return void
*/
public function init()
{
parent::init();
if ($this->_table->getFatherRule())
{
$this->_father = $this->findParentRow(get_parent_class($this->_table),$this->_table->getFatherRule());
}
$this->_columnMap = $this->_table->getColumnMap();
}
/**
* Retrieve row field value
*
* @param string $columnName The user-specified column name.
* @return string The corresponding column value.
* @throws Zend_Db_Table_Row_Exception if the $columnName is not a column in the row.
*/
public function __get($columnName)
{
$columnName = $this->_transformColumn($columnName);
if (!array_key_exists($columnName, $this->_data)) {
if ($this->_father)
{
return $this->_father->$columnName;
}
else
{
require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Specified column \"$columnName\" is not in the row");
}
}
else
{
return $this->_data[$columnName];
}
}
/**
* Set row field value
*
* @param string $columnName The column key.
* @param mixed $value The value for the property.
* @return void
* @throws Zend_Db_Table_Row_Exception
*/
public function __set($columnName, $value)
{
$columnName = $this->_transformColumn($columnName);
if (!array_key_exists($columnName, $this->_data)) {
if ($this->_father)
{
$this->_father->$columnName=$value;
}
else
{
require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Specified column \"$columnName\" is not in the row");
}
}
$this->_data[$columnName] = $value;
$this->_modifiedFields[$columnName] = true;
}
/**
* Test existence of row field
*
* @param string $columnName The column key.
* @return boolean
*/
public function __isset($columnName)
{
$columnName = $this->_transformColumn($columnName);
if (array_key_exists($columnName, $this->_data))
{
return true;
}
else if ($this->_father)
{
return $this->_father->__isset($columnName);
}
else
{
return false;
}
}
/**
* Store table, primary key and data in serialized object
*
* @return array
*/
public function __sleep()
{
return array('_tableClass', '_primary', '_data', '_cleanData', '_readOnly' ,'_modifiedFields','_father');
}
/**
* Saves the properties to the database.
*
* This performs an intelligent insert/update, and reloads the
* properties with fresh data from the table on success.
*
* @return mixed The primary key value(s), as an associative array if the
* key is compound, or a scalar if the key is single-column.
*/
public function save()
{
parent::save();
if ($this->_father)
{
$this->_father->save();
}
}
/**
* Query a parent table to retrieve the single row matching the current row.
*
* @param string|Zend_Db_Table_Abstract $parentTable
* @param string OPTIONAL $ruleKey
* @return Zend_Db_Table_Row_Abstract Query result from $parentTable
* @throws Zend_Db_Table_Row_Exception If $parentTable is not a table or is not loadable.
*/
public function findParentRow($parentTable, $ruleKey = null, Zend_Db_Table_Select $select = null)
{
$db = $this->_getTable()->getAdapter();
if (is_string($parentTable)) {
try {
@Zend_Loader::loadClass($parentTable);
} catch (Zend_Exception $e) {
require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception($e->getMessage());
}
$parentTable = new $parentTable(array('db' => $db));
}
if (! $parentTable instanceof Zend_Db_Table_Abstract) {
$type = gettype($parentTable);
if ($type == 'object') {
$type = get_class($parentTable);
}
require_once 'Zend/Db/Table/Row/Exception.php';
throw new Zend_Db_Table_Row_Exception("Parent table must be a Zend_Db_Table_Abstract, but it is $type");
}
try {
$map = $this->_prepareReference($this->_getTable(), $parentTable, $ruleKey);
if ($select === null) {
$select = $parentTable->select();
} else {
$select->setTable($parentTable);
}
for ($i = 0; $i < count($map[Zend_Db_Table_Abstract::COLUMNS]); ++$i) {
$dependentColumnName = $db->foldCase($map[Zend_Db_Table_Abstract::COLUMNS][$i]);
$value = $this->_data[$dependentColumnName];
// Use adapter from parent table to ensure correct query construction
$parentDb = $parentTable->getAdapter();
$parentColumnName = $parentDb->foldCase($map[Zend_Db_Table_Abstract::REF_COLUMNS][$i]);
$parentColumn = $parentDb->quoteIdentifier($parentColumnName, true);
$parentInfo = $parentTable->info();
$type = $parentInfo[Zend_Db_Table_Abstract::METADATA][$parentColumnName]['DATA_TYPE'];
$select->where("$parentColumn = ?", $value, $type);
}
return $parentTable->fetchRow($select);
}
catch (Zend_Db_Table_Exception $e)
{
if ($this->_father)
{
return $this->_father->findParentRow($parentTable,$ruleKey,$select);
}
else
{
throw $e;
}
}
}
I can implement Zend_Db_Table_Row_Abstract::findParentRow,but lack implement the Zend_Db_Table_Row_Abstract::findDependentRowset and Zend_Db_Table_Row_Abstract::findManyToManyRowset.
--
Fernando Chucre - LPIC-1
http://www.horizontesdigitais.com
没有评论:
发表评论