Hello all,
I wanna see in Zend_Db_Table_Abstract, Zend_Db_Table_Rowset_Abstract and Zend_Db_Table_Row_Abstract new features like column name alias and inheritance with 2 or more tables. I write a email before about this. So I and my friend Milfont (Java developer) write 3 extends class. The first feature is column alias map and in sequence inheritance of class with 2 or 3 tables.
Column Alias Map
Well, I when start work with ZF I won much productivity in the project. But when I start write the model classes with Zend_Db_Table to make ORM I discovered some small problems. The first are column alias map. ZF implements Active Record, so the object that has the data to know how salver. And the name of attributes are the column names. But I need changed name in attributes. And I need a lot times. So write a new class extended of Zend_Db_Table_Row_Abstract are impracticable. I need an attribute which maps column in class that extends Zend_Db_Table_Abstract.
When I start study the way to write the solution I find the method "protected function _transformColumn($columnName)". This method throw an exption if $columnName is not a string or returm the $columnName.
The description of this method:
/**
* Transform a column name from the user-specified form
* to the physical form used in the database.
* You can override this method in a custom Row class
* to implement column name mappings, for example inflection.
*
* @param string $columnName Column name given.
* @return string The column name after transformation applied (none by default).
* @throws Zend_Db_Table_Row_Exception if the $columnName is not a string.
*/
And change this method
/**
* Initialize object
*
* Called from {@link __construct()} as final step of object instantiation.
*
* @return void
*/
public function init()
{
$this->_initializeColumnMap();
}
This can be in __contruct() method.
In Zend_Db_Table_Row_Abstract I create this:
/**
* Information provided by the init() method. This data maped the column names in table.
*
* @var array
*/
protected $_columnMap = array();
and change theses:
/**
* Initialize object
*
* Called from {@link __construct()} as final step of object instantiation.
*
* @return void
*/
public function init()
{
$this->_columnMap = $this->_table->getColumnMap();
}
/**
* Transform a column name from the user-specified form
* to the physical form used in the database.
* You can override this method in a custom Row class
* to implement column name mappings, for example inflection.
*
* @param string $columnName Column name given.
* @return string The column name after transformation applied (none by default).
* @throws Zend_Db_Table_Row_Exception if the $columnName is not a string.
*/
protected function _transformColumn($columnName)
{
if ($this->_columnMap[$columnName]) {
return $this->_columnMap[$columnName];
}
else
{
return $columnName;
}
}
/**
* Returns the column/value data as an array.
*
* @return array
*/
public function toArray()
{
$_data = array();
foreach ($this->_data as $key=>$val)
{
$_k = $this->_table->getMapedColumn($key);
$_data[$_k] = $this->_data[$key];
}
return $_data;
}
In class Zend_Db_Table_Rowset_Abstract I change this method
/**
* Returns all data as an array.
*
* Updates the $_data property with current row object values.
*
* @return array
*/
public function toArray()
{
// @todo This works only if we have iterated through
// the result set once to instantiate the rows.
$_data = array();
foreach ($this->_data as $_lk=>$line)
{
foreach($line as $key=>$val)
{
$_k = $this->_table->getMapedColumn($key);
$_data[$_lk][$_k] = $line[$key];
}
}
foreach ($this->_rows as $i => $row) {
$this->_data[$i] = $row->toArray();
}
return $_data;
}
So, now I got what I wanted. But when I pass the parameter $where in Zend_Db_Table_Abstract::fetchAll() method I still needed to pass the real name. So i write fallow method. These methods:
/**
* Return the maped column name
*
* @param string $col_real Real column name given.
* @return string The column name after transformation applied.
*/
public function getMapedColumn($col_real)
{
$return = array_search($col_real, $this->_columnMap);
return ($return)?$return:$col_real;
}
/**
* Return the real column name
*
* @param string $map_col Maped column name given.
* @return string The column name after transformation applied.
*/
public function getRealColumn($map_col)
{
$return = $this->_columnMap[$map_col];
return ($return)?$return:$map_col;
}
/**
* Return the select with column names translated based in Column Map
*
* @param Zend_Db_Table_Select $select Object to be translated
* @param Zend_Db_Table_Select Object translated
*/
protected function _translateColumnMap(Zend_Db_Table_Select $select)
{
$where = $select->getPart('where');
$order = $select->getPart('order');
$select->reset('where');
$select->reset('order');
foreach($order as $k)
{
$col_name = $this->getRealColumn($k[0]);
$select->order(($k[1])?"{$col_name} {$k[1]}":$col_name);
}
foreach($where as &$l)
{
preg_match('/((AND|OR) \()?([a-zA-Z0-9_-]+)([=<> ])/',$l,$match);
$col_name = $this->getRealColumn($match[3]);
$l = str_replace("({$match[3]}{$match[4]}","({$col_name}{$match[4]}",$l);
if ($match[1]=='OR (')
{
$l = str_replace("OR (",'',$l);
$l = str_replace(")",'',$l);
$select->orWhere($l);
}
else if ($match[1]=='AND (')
{
$l = str_replace("AND (",'',$l);
$l = str_replace(")",'',$l);
$select->where($l);
}
else
{
$l = str_replace(")",'',$l);
$l = str_replace("(",'',$l);
$select->where($l);
}
}
return $select;
}
The method _translateColumnMap thanslate only the names in where clausule and order by and problaly have bugs.
--
Fernando Chucre - LPIC-1
http://www.horizontesdigitais.com
I wanna see in Zend_Db_Table_Abstract, Zend_Db_Table_Rowset_Abstract and Zend_Db_Table_Row_Abstract new features like column name alias and inheritance with 2 or more tables. I write a email before about this. So I and my friend Milfont (Java developer) write 3 extends class. The first feature is column alias map and in sequence inheritance of class with 2 or 3 tables.
Column Alias Map
Well, I when start work with ZF I won much productivity in the project. But when I start write the model classes with Zend_Db_Table to make ORM I discovered some small problems. The first are column alias map. ZF implements Active Record, so the object that has the data to know how salver. And the name of attributes are the column names. But I need changed name in attributes. And I need a lot times. So write a new class extended of Zend_Db_Table_Row_Abstract are impracticable. I need an attribute which maps column in class that extends Zend_Db_Table_Abstract.
When I start study the way to write the solution I find the method "protected function _transformColumn($columnName)". This method throw an exption if $columnName is not a string or returm the $columnName.
The description of this method:
/**
* Transform a column name from the user-specified form
* to the physical form used in the database.
* You can override this method in a custom Row class
* to implement column name mappings, for example inflection.
*
* @param string $columnName Column name given.
* @return string The column name after transformation applied (none by default).
* @throws Zend_Db_Table_Row_Exception if the $columnName is not a string.
*/
I started solution modules from here. I needed Write methods to sanizete map and implements new _transformColumn.
So in Zend_Db_Table_Abstract I add these attributes and methods
/**
* Column map
* protected $_columnMap = array('wanted_name'=>'real_name');
*
* @var array
*/
protected $_columnMap = array();
/**
* @return array
*/
public function getColumnMap()
{
return $this->_columnMap;
}
/**
* Initializa columnMap
*
* Called from {@link init()}
*
* @return void
*/
protected function _initializeColumnMap()
{
foreach($this->_columnMap as $col_maped=>$col_real)
{
if (in_array($col_maped,$this->_cols))
{
throw new Zend_Db_Table_Row_Exception("Mapped column name must be not real name column");
}
if (!in_array($col_real,$this->_cols))
{
throw new Zend_Db_Table_Row_Exception("Real column name must be exist in table");
}
}
$_temp = array_combine($this->_cols,$this->_cols);
$this->_columnMap = array_flip($this->_columnMap);
$this->_columnMap = array_merge($_temp,$this->_columnMap);
$this->_columnMap = array_flip($this->_columnMap);
}
So in Zend_Db_Table_Abstract I add these attributes and methods
/**
* Column map
* protected $_columnMap = array('wanted_name'=>'real_name');
*
* @var array
*/
protected $_columnMap = array();
/**
* @return array
*/
public function getColumnMap()
{
return $this->_columnMap;
}
/**
* Initializa columnMap
*
* Called from {@link init()}
*
* @return void
*/
protected function _initializeColumnMap()
{
foreach($this->_columnMap as $col_maped=>$col_real)
{
if (in_array($col_maped,$this->_cols))
{
throw new Zend_Db_Table_Row_Exception("Mapped column name must be not real name column");
}
if (!in_array($col_real,$this->_cols))
{
throw new Zend_Db_Table_Row_Exception("Real column name must be exist in table");
}
}
$_temp = array_combine($this->_cols,$this->_cols);
$this->_columnMap = array_flip($this->_columnMap);
$this->_columnMap = array_merge($_temp,$this->_columnMap);
$this->_columnMap = array_flip($this->_columnMap);
}
And change this method
/**
* Initialize object
*
* Called from {@link __construct()} as final step of object instantiation.
*
* @return void
*/
public function init()
{
$this->_initializeColumnMap();
}
This can be in __contruct() method.
In Zend_Db_Table_Row_Abstract I create this:
/**
* Information provided by the init() method. This data maped the column names in table.
*
* @var array
*/
protected $_columnMap = array();
and change theses:
/**
* Initialize object
*
* Called from {@link __construct()} as final step of object instantiation.
*
* @return void
*/
public function init()
{
$this->_columnMap = $this->_table->getColumnMap();
}
/**
* Transform a column name from the user-specified form
* to the physical form used in the database.
* You can override this method in a custom Row class
* to implement column name mappings, for example inflection.
*
* @param string $columnName Column name given.
* @return string The column name after transformation applied (none by default).
* @throws Zend_Db_Table_Row_Exception if the $columnName is not a string.
*/
protected function _transformColumn($columnName)
{
if ($this->_columnMap[$columnName]) {
return $this->_columnMap[$columnName];
}
else
{
return $columnName;
}
}
/**
* Returns the column/value data as an array.
*
* @return array
*/
public function toArray()
{
$_data = array();
foreach ($this->_data as $key=>$val)
{
$_k = $this->_table->getMapedColumn($key);
$_data[$_k] = $this->_data[$key];
}
return $_data;
}
In class Zend_Db_Table_Rowset_Abstract I change this method
/**
* Returns all data as an array.
*
* Updates the $_data property with current row object values.
*
* @return array
*/
public function toArray()
{
// @todo This works only if we have iterated through
// the result set once to instantiate the rows.
$_data = array();
foreach ($this->_data as $_lk=>$line)
{
foreach($line as $key=>$val)
{
$_k = $this->_table->getMapedColumn($key);
$_data[$_lk][$_k] = $line[$key];
}
}
foreach ($this->_rows as $i => $row) {
$this->_data[$i] = $row->toArray();
}
return $_data;
}
So, now I got what I wanted. But when I pass the parameter $where in Zend_Db_Table_Abstract::fetchAll() method I still needed to pass the real name. So i write fallow method. These methods:
/**
* Return the maped column name
*
* @param string $col_real Real column name given.
* @return string The column name after transformation applied.
*/
public function getMapedColumn($col_real)
{
$return = array_search($col_real, $this->_columnMap);
return ($return)?$return:$col_real;
}
/**
* Return the real column name
*
* @param string $map_col Maped column name given.
* @return string The column name after transformation applied.
*/
public function getRealColumn($map_col)
{
$return = $this->_columnMap[$map_col];
return ($return)?$return:$map_col;
}
/**
* Return the select with column names translated based in Column Map
*
* @param Zend_Db_Table_Select $select Object to be translated
* @param Zend_Db_Table_Select Object translated
*/
protected function _translateColumnMap(Zend_Db_Table_Select $select)
{
$where = $select->getPart('where');
$order = $select->getPart('order');
$select->reset('where');
$select->reset('order');
foreach($order as $k)
{
$col_name = $this->getRealColumn($k[0]);
$select->order(($k[1])?"{$col_name} {$k[1]}":$col_name);
}
foreach($where as &$l)
{
preg_match('/((AND|OR) \()?([a-zA-Z0-9_-]+)([=<> ])/',$l,$match);
$col_name = $this->getRealColumn($match[3]);
$l = str_replace("({$match[3]}{$match[4]}","({$col_name}{$match[4]}",$l);
if ($match[1]=='OR (')
{
$l = str_replace("OR (",'',$l);
$l = str_replace(")",'',$l);
$select->orWhere($l);
}
else if ($match[1]=='AND (')
{
$l = str_replace("AND (",'',$l);
$l = str_replace(")",'',$l);
$select->where($l);
}
else
{
$l = str_replace(")",'',$l);
$l = str_replace("(",'',$l);
$select->where($l);
}
}
return $select;
}
The method _translateColumnMap thanslate only the names in where clausule and order by and problaly have bugs.
--
Fernando Chucre - LPIC-1
http://www.horizontesdigitais.com
没有评论:
发表评论