这个问题可能比我最初想的更容易得到答案,实际上......
让我们从你现在拥有的开始:
- 一个模型类,扩展
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_at 和 updated_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_at 和updated_at 两个字段的类型既不是date 也不是timestamp,Doctrine_Template_Listener_Timestampable 将自动使用UNIX 时间戳——多么方便!
由于您不想定义 type 以用于您的每个模型中的这些字段,我们将修改我们的 MyTimestampable 类。
请记住,我们说它正在扩展 Doctrine_Template_Timestampable,它负责配置行为...
因此,我们使用 type 而不是 date 和 timestamp 覆盖该配置:
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 的行为
- 并且只覆盖它的配置
- 因此我们可以随心所欲地使用它,每个模型中只需要一行代码。
我会让你做一些更密集的测试,但我希望这会有所帮助!
玩得开心:-)