【问题标题】:Use Unix timestamp in Doctrine Timestampable在 Doctrine Timestampable 中使用 Unix 时间戳
【发布时间】:2010-11-14 02:05:19
【问题描述】:

如何将 Unix 时间戳与 Doctrine Timestampable 行为结合使用?我找到了以下代码 sn -p here,但我宁愿不要在任何地方手动添加:

$this->actAs('Timestampable', array(
'created' => array('name' => 'created_at',
    'type'    =>  'integer',
    'format'  =>  'U',
    'disabled' => false,
    'options' =>  array()),
'updated' => array('name'    =>  'updated_at',
    'type'    =>  'integer',
    'format'  =>  'U',
    'disabled' => false,
    'options' =>  array())));

【问题讨论】:

  • 为什么不使用使用 DATETIME 字段的默认时间戳?
  • 更容易与简单的纪元图章交互。

标签: php doctrine epoch unix-timestamp


【解决方案1】:

一种方法是使用医生的侦听器在获取记录时和保存之前创建一个等效的 unix 时间戳:

class Base extends Doctrine_Record_Listener
{
    public function preHydrate(Doctrine_Event $event)
    {
        $data = $event->data;

        $data['unix_created_at'] = strtotime($data['created_at']);
        $data['unix_updated_at'] = strtotime($data['updated_at']);

        $event->data = $data;
    }
}

这可能是您在需要 created_at 和 updated_at 功能的任何东西中扩展的基类。

我敢肯定,只要稍加修改,您就可以遍历 $data 并转换所有日期时间字段 'unix_'.$field_name。

祝你好运

【讨论】:

    【解决方案2】:

    这个问题可能比我最初想的更容易得到答案,实际上......

    让我们从你现在拥有的开始:

    • 一个模型类,扩展Doctrine_Record
      • 我将把这个类称为Test,作为我的例子。
      • 在此 Test 模型中,您希望使用 Timestampable 行为,但使用 UNIX 时间戳,而不是 datetime
      • 而且您不需要在模型中编写大量配置内容就可以做到这一点。
        (我可以理解:在某处忘记一行和 DB 中的错误数据的风险较小)
    • 一个已配置好的项目和一切
      • 这意味着您了解 Doctrine 的内容
      • 而且我不会谈论基础知识

    解决此问题的方法是不使用 Doctrine 附带的默认 Timestampable 行为,而是使用您将定义的另一种行为。
    这意味着,在您的模型中,您将在 setTableDefinition 方法的底部有类似的内容:

    $this->actAs('MyTimestampable');
    

    (我想这也可以在 setUp 方法中使用,顺便说一句——实际上它可能是真实的地方)


    我们现在要做的就是定义MyTimestampable 的行为,让它做我们想做的事。
    由于 Doctrine 的 Doctrine_Template_Timestampable 已经很好地完成了这项工作(当然格式除外),我们将继承它;希望这将意味着编写更少的代码;-)

    所以,我们这样声明我们的行为类:

    class MyTimestampable extends Doctrine_Template_Timestampable
    {
        // Here it will come ^^
    }
    

    现在,让我们看看 Doctrine_Template_Timestampable 在 Doctrine 的代码源中实际做了什么:

    • 一些配置created_atupdated_at 两个字段)
    • 还有以下行,它注册了一个监听器:


    $this->addListener(new Doctrine_Template_Listener_Timestampable($this->_options));
    

    我们来看看这个的来源;我们注意到这部分:

    if ($options['type'] == 'date') {
        return date($options['format'], time());
    } else if ($options['type'] == 'timestamp') {
        return date($options['format'], time());
    } else {
        return time();
    }
    

    这意味着如果created_atupdated_at 两个字段的类型既不是date 也不是timestampDoctrine_Template_Listener_Timestampable 将自动使用UNIX 时间戳——多么方便!


    由于您不想定义 type 以用于您的每个模型中的这些字段,我们将修改我们的 MyTimestampable 类。
    请记住,我们说它正在扩展 Doctrine_Template_Timestampable,它负责配置行为...

    因此,我们使用 type 而不是 datetimestamp 覆盖该配置:

    class MyTimestampable extends Doctrine_Template_Timestampable
    {
        protected $_options = array(
            'created' =>  array('name'          =>  'created_at',
                                'alias'         =>  null,
                                'type'          =>  'integer',
                                'disabled'      =>  false,
                                'expression'    =>  false,
                                'options'       =>  array('notnull' => true)),
            'updated' =>  array('name'          =>  'updated_at',
                                'alias'         =>  null,
                                'type'          =>  'integer',
                                'disabled'      =>  false,
                                'expression'    =>  false,
                                'onInsert'      =>  true,
                                'options'       =>  array('notnull' => true)));
    }
    

    我们之前说过我们的模型是MyTimestampable,而不是Timestampable...所以,现在,让我们看看结果;-)

    如果我们考虑 Test 的这个模型类:

    class Test extends Doctrine_Record
    {
        public function setTableDefinition()
        {
            $this->setTableName('test');
            $this->hasColumn('id', 'integer', 4, array(
                 'type' => 'integer',
                 'length' => 4,
                 'unsigned' => 0,
                 'primary' => true,
                 'autoincrement' => true,
                 ));
            $this->hasColumn('name', 'string', 32, array(
                 'type' => 'string',
                 'length' => 32,
                 'fixed' => false,
                 'primary' => false,
                 'notnull' => true,
                 'autoincrement' => false,
                 ));
            $this->hasColumn('value', 'string', 128, array(
                 'type' => 'string',
                 'length' => 128,
                 'fixed' => false,
                 'primary' => false,
                 'notnull' => true,
                 'autoincrement' => false,
                 ));
            $this->hasColumn('created_at', 'integer', 4, array(
                 'type' => 'integer',
                 'length' => 4,
                 'unsigned' => 0,
                 'primary' => false,
                 'notnull' => true,
                 'autoincrement' => false,
                 ));
            $this->hasColumn('updated_at', 'integer', 4, array(
                 'type' => 'integer',
                 'length' => 4,
                 'unsigned' => 0,
                 'primary' => false,
                 'notnull' => false,
                 'autoincrement' => false,
                 ));
            $this->actAs('MyTimestampable');
        }
    }
    

    映射到以下 MySQL 表:

    CREATE TABLE  `test1`.`test` (
      `id` int(11) NOT NULL auto_increment,
      `name` varchar(32) NOT NULL,
      `value` varchar(128) NOT NULL,
      `created_at` int(11) NOT NULL,
      `updated_at` int(11) default NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8
    

    我们可以这样在表中创建两行:

    $test = new Test();
    $test->name = 'Test 1';
    $test->value = 'My Value 2';
    $test->save();
    
    $test = new Test();
    $test->name = 'Test 2';
    $test->value = 'My Value 2';
    $test->save();
    

    如果我们检查数据库中的值,我们会得到这样的结果:

    mysql> select * from test;
    +----+--------+----------------+------------+------------+
    | id | name   | value          | created_at | updated_at |
    +----+--------+----------------+------------+------------+
    |  1 | Test 1 | My Value 1     | 1248805507 | 1248805507 |
    |  2 | Test 2 | My Value 2     | 1248805583 | 1248805583 |
    +----+--------+----------------+------------+------------+
    2 rows in set (0.00 sec)
    

    所以,我们似乎可以创建行了 ;-)


    现在,让我们获取并更新第二行:

    $test = Doctrine::getTable('Test')->find(2);
    $test->value = 'My New Value 2';
    $test->save();
    

    然后,回到数据库,我们现在得到了这个:

    mysql> select * from test;
    +----+--------+----------------+------------+------------+
    | id | name   | value          | created_at | updated_at |
    +----+--------+----------------+------------+------------+
    |  1 | Test 1 | My Value 1     | 1248805507 | 1248805507 |
    |  2 | Test 2 | My New Value 2 | 1248805583 | 1248805821 |
    +----+--------+----------------+------------+------------+
    2 rows in set (0.00 sec)
    

    updated_at 字段已更新,created_at 字段未更改;这似乎也不错;-)


    所以,为了简短起见,请放在几个要点中,然后总结一下:

    • 我们的模型类充当我们自己的MyTimestampable,而不是默认的Timestampable
    • 我们的行为扩展了 Doctrine 的行为
    • 并且只覆盖它的配置
      • 因此我们可以随心所欲地使用它,每个模型中只需要一行代码。


    我会让你做一些更密集的测试,但我希望这会有所帮助!
    玩得开心:-)

    【讨论】:

    • 这是一个很好的答案,应该是 +100。
    • 谢谢!好吧,实际上,它已经 +100 了:在这个问题上有一个赏金(价值 100 代表);我的答案已被接受^^
    【解决方案3】:

    它非常简单。只需使用 datetime 参数为您的字段创建一个 Setter 方法,然后使用 tostring 方法将其存储为整数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-28
      • 1970-01-01
      • 2013-03-23
      • 2021-02-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多