6

Doctrine Timestampableの動作でUnixタイムスタンプを使用するにはどうすればよいですか?ここで次のコードスニペットを見つけましたが、手動でどこにでも追加したくありません。

$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())));
4

3 に答える 3

33

これは、私が最初に考えたよりも簡単に答えが得られるかもしれない質問です.

あなたが今持っているものから始めましょう:

  • 拡張するモデルクラスDoctrine_Record
    • 私の例では、このクラスを呼び出しますTest
    • このTestモデルでは、動作を使用したいのですが、値Timestampableではなく UNIX タイムスタンプを使用します。datetime
    • そして、モデルに多くの構成を記述する必要なく、これが必要です。
      (私はそれを理解できます:どこかで1行を忘れて、DBの間違ったデータであるリスクが少なくなります)
  • 構成されたプロジェクトとすべて
    • これは、あなたが Doctrine を使っていることを知っていることを意味します
    • 基本的なことはお話ししません

この問題の解決策Timestampableは、Doctrine に付属するデフォルトの動作を使用するのではなく、別の動作を定義することです。
つまり、モデルでは、setTableDefinitionmethodの下部に次のようなものがあります。

$this->actAs('MyTimestampable');

(私はこれもsetUpメソッドに入ることができると思います.btw - 実際には本当の場所かもしれません)


私たちが今しなければならないことは、そのMyTimestampable振る舞いを定義することです。
DoctrineDoctrine_Template_Timestampableはすでにかなりうまく機能しているので(もちろん、フォーマットを除いて)、それを継承します。うまくいけば、それは書くコードが少なくなることを意味します;-)

したがって、次のように動作クラスを宣言します。

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

Doctrine_Template_Timestampableでは、Doctrine のコード ソースで実際に何をするか見てみましょう:

  • 少しの設定(2 つのフィールド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();
}

これは、2 つのフィールドcreated_atupdated_atフィールドの型がdatenortimestampでない場合、Doctrine_Template_Listener_Timestampable自動的に UNIX タイムスタンプを使用することを意味します。これは非常に便利です。


typeすべてのモデルでこれらのフィールドに使用するを定義したくないので、MyTimestampableクラスを変更します。 ビヘイビアーの設定を担当するのは
extends であると言ったことを思い出してください...Doctrine_Template_Timestampable

そのため、 andtype以外を使用して、その構成をオーバーライドします。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

この方法でテーブルに 2 つの行を作成できます。

$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();

DB の値を確認すると、次のような結果が得られます。

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)

したがって、行の作成は問題ないようです ;-)


それでは、2 行目をフェッチして更新しましょう。

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

DB に戻ると、次のようになります。

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は変更されていません。これもOKのようです;-)


したがって、物事を短くするために、いくつかの箇条書きに収まるようにし、かなり要約します:

  • 私たちのモデルクラスMyTimestampableは、デフォルトではなく、独自の として機能しますTimestampable
  • 私たちの行動はDoctrineの行動を拡張します
  • そして、その構成をオーバーライドするだけです
    • したがって、モデルごとに 1 行のコードだけで、必要に応じて使用できます。


より集中的なテストをいくつか実施させていただきますが、これがお役に立てば幸いです。
楽しんでください:-)

于 2009-07-28T19:02:13.133 に答える
2

1 つの方法は、doctorine のリスナーを使用して、レコードが取得されて保存される前に同等の 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 を変換できると確信しています。

幸運を

于 2009-07-28T17:45:50.790 に答える