23 February 2006
This post may be outdated due to it was written on 2006. The links may be broken. The code may be not working anymore. Leave comments if needed.
DBIx::Class is great, 所以我在最近写的论坛代码 Foorum 中就使用了 DBIx::Class 作为我的 Model. (use base 'Catalyst::Model::DBIC';)
但我挺喜欢 Class::DBI 的 Trigger,而 DBIx::Class 要使用这个东西似乎比较麻烦。按它 wiki 上的说法似乎要载入 use base qw/ DBIx::Class::CDBICompat::Triggers DBIx::Class::Core/; 没有其他的办法。

我在写 Foorum 的注册程序,表 user 里有一个字段是 register_date 类型为 DATETIME。如果用 Trigger 的话似乎简单一些, register_date = NOW() 就可以(用 mysql 的函数)。

还好 DBIx::Class 也提供了 inflate. 所以我就用这个来完成我的任务。 inflate 在这里只是一个暗喻,它主要用于在表的某一字段的数据存入或取出之前做一些变动。 deflate 用于做存入前的变动,而 inflate 做取出后的变动。

在无法用 register_date = NOW() 之后,要将 localtime 或 gmtime 转为 DATATIME 类型似乎比较麻烦。还好 CPAN 上有一模块为 DateTime::Format::MySQL 用于将 DateTime 对象转为 MySQL 所需要的类型。所以代码很简单:

package Foorum::Model::DBIC::User;

use strict;
use base 'Foorum::Model::DBIC';

use DateTime::Format::MySQL;

__PACKAGE__->inflate_column( 'register_date',
{ inflate => sub { return shift; },
deflate => sub { DateTime::Format::MySQL->format_datetime( shift ); } }
);

而当我们存入数据时就可以使用:
use DateTime;
$c->model('DBIC')->table('user')->create({
username => $username,
password => $computed,
email => $email,
register_date => DateTime->now,
register_ip => $c->req->address,
});
当 create 创建新的 record 时,将传入的 register_date(这里是 DateTime->now;)先用 deflate 做一些变动,这里将它(shift 指的是 DateTime->now)处理(format_datetime)后再存入。
而 inflate 反一下,指取出后立即处理的匿名函数。我这里只是直接返回,因为我不需要再处理。如果你想它取出来也是一个 DateTime 对象好方便你进一步处理的话,可以将 inflate 的函数改为:
inflate => sub { DateTime::Format::MySQL->parse_datetime( shift ); },
:) have fun. 如有疑问,发 mail 跟我探讨。 thanks.


blog comments powered by Disqus