3

据我了解,在 Zend 框架中处理日期的最佳方法是从数据库中选择它们作为 Unix 时间戳。

从数据库日期值快速创建日期

// SELECT UNIX_TIMESTAMP(my_datetime_column) FROM my_table
$date = new Zend_Date($unixtimestamp, Zend_Date::TIMESTAMP);

我认为在 Oracle 中实际上没有简单的方法来选择日期作为 Unix 时间戳或 ISO-8601 格式,这很痛苦——这两种格式Zend_Date最了解。

但是我确实编写了一个函数来选择日期作为 PL/SQL 中的 unix 时间戳,所以我现在可以实际执行此操作。

使用Zend_Db_Expr,我现在可以选择我的日期作为 Unix 时间戳:

$select = $db->select()
             ->from(array('p' => 'products'),
                    array(
                        'product_id',
                        'product_date' => new Zend_Db_Expr('toUnixTimestamp(product_date)')
                    )
               );

$results = $db->fetchAll($select);

您将对任何 RDMS 使用类似的查询 - 大多数都具有时间戳功能。

我觉得这很烦人,因为现在我必须遍历 $results 以手动将时间戳转换为 Zend_Date 对象:

foreach($results as $result){
    $productDate = new Zend_Date($result['product_date'], Zend_Date::TIMESTAMP);
    echo $productDate->toString('dd/MMM/yyyy HH:mm:ss');
}

我希望我的模型返回时间戳已经转换为 Zend_Date 的 $results。我不想在每个数据访问函数中编写一个循环来为我执行此操作。

所以要解决我的实际问题:

有谁知道 Zend_Db 的一种方法,可以在结果集上设置某种后处理,从而自动将时间戳转换为 Zend_Date 对象?

4

2 回答 2

6

我遇到过我想这样做的场景。这是我使用的解决方案:

  • 为 Zend_Db_Table_Row 创建了一个扩展行类并重载了 __get() 和 __set() 超级方法
  • 在我想使用日期对象的特定类/表中,创建了适当的方法来完成繁重的工作

这是我在项目中使用的扩展行类的简化版本:

/**
 * @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);
    }
}

对于我们单独的表类,我们重写如下函数:

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;
    }
}

现在,每次访问该字段时都创建一个新的 Zend_Date 对象有一些开销,所以在我们的类中,我们采取了额外的措施来缓存日期对象等,但我不希望这妨碍向您展示解决方案。

于 2009-10-30T11:08:16.330 回答
0

使用 Zend_Table 并让您的表返回扩展Zend_Db_Table_Row_Abstract的自定义行对象。然后在该行上有一个方法,例如

function getDate() {
    return new Zend_Date($this->datecol, Zend_Date::TIMESTAMP);
}
于 2009-10-30T04:45:29.793 回答