Automatically selecting dates from databases as Zend_Date objects
From what I understand, the best way to deal with dates in the Zend Framework is to select them as a Unix timestamp from the database.
Quick Creation of Dates from Database Date Values
// SELECT UNIX_TIMESTAMP(my_datetime_column) FROM my_table
$date = new Zend_Date($unixtimestamp, Zend_Date::TIMESTAMP);
I think it's a pain that there is actually no easy way in Oracle to either select dates as Unix timestamps or in ISO-8601 format - which are the two formats Zend_Date
knows best.
But I did write a function to select dates as unix timestamps in PL/SQL, so I can actually do this now.
Using Zend_Db_Expr
, I can now s开发者_如何学Pythonelect my dates as Unix timestamps:
$select = $db->select()
->from(array('p' => 'products'),
array(
'product_id',
'product_date' => new Zend_Db_Expr('toUnixTimestamp(product_date)')
)
);
$results = $db->fetchAll($select);
You would use a similar query for any RDMS - most have a timestamp function.
I find this anoying because now I have to loop through $results to transform the timestamp to a Zend_Date object manually:
foreach($results as $result){
$productDate = new Zend_Date($result['product_date'], Zend_Date::TIMESTAMP);
echo $productDate->toString('dd/MMM/yyyy HH:mm:ss');
}
I want my Model to return $results where the timestamps are already transformed to Zend_Date. I don't want to have to write a loop in every data-access function to do this for me.
So to get to the point of my actual question:
Does anyone know of a way with Zend_Db, to set up some sort of post-processing on the result set, thus converting the timestamps to Zend_Date objects automatically?
I've encountered scenarios where I've wanted to do this. Here is the solution that I've used:
- Created an extended row class for Zend_Db_Table_Row and overloaded the __get() and __set() super-methods
- In the specific classes/tables that I want to use date objects, created the appropriate methods to do the heavy lifting
Here is a dumbed-down version of the extended row class that I use on my projects:
/**
* @category FireUp
* @package FireUp_Db
* @copyright Copyright (c) 2007-2009 Fire Up Media, Inc. (http://www.fireup.net)
* @license http://dev.fireup.net/license/mit MIT License
* @uses Zend_Db_Table_Row
*/
class FireUp_Db_Table_Row extends Zend_Db_Table_Row_Abstract
{
/**
* Retrieve row field value
*
* Checks for the existence of a special method to apply additional handling for the field data and calls the method if it exists
*
* @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($key)
{
$inflector = new Zend_Filter_Word_UnderscoreToCamelCase();
$method = '_get' . $inflector->filter($key);
if (method_exists($this, $method))
{
return $this->{$method}();
}
return parent::__get($key);
}
/**
* Set row field value
*
* Checks for the existence of a special method to apply additional handling for the field data and calls the method if it exists
*
* @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($key, $value)
{
$inflector = new Zend_Filter_Word_UnderscoreToCamelCase();
$method = '_set' . $inflector->filter($key);
if (method_exists($this, $method))
{
return $this->{$method}($value);
}
return parent::__set($key, $value);
}
}
For our individual table classes, we override the functions as such:
class EntityRecord extends FireUp_Db_Table_Row
{
protected function _getDateCreated()
{
return new Zend_Date($this->_data['date_created'], Zend_Date::ISO_8601);
}
protected function _setDateCreated($value)
{
if ($value instanceof Zend_Date)
{
$value = $value->toString('YYYY-MM-dd HH:mm:ss');
}
$this->_data['date_created'] = $value;
$this->_modifiedFields['date_created'] = true;
}
}
Now, creating a new Zend_Date object everytime that the field would be accessed has some overhead, so in our classes, we take additional measures to cache the date objects, etc, but I didn't want that to get in the way of showing you the solution.
Use Zend_Table and have your table return you custom row objects that extend Zend_Db_Table_Row_Abstract
. Then just have a method on that row like
function getDate() {
return new Zend_Date($this->datecol, Zend_Date::TIMESTAMP);
}
精彩评论