Использовать временную метку Unix в методе времени доктрины

Как использовать временные метки Unix с поведением временной отметки Doctrine? Здесь я нашел следующий фрагмент кода, но я бы не добавил его вручную:

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

Это вопрос, который может получить ответ легче, чем то, что я впервые подумал, на самом деле …

Начнем с того, что у вас есть сейчас:

  • класс модели, который расширяет Doctrine_Record
    • Я буду называть этот класс Test , для моего примера (ов).
    • В этой Test модели вы хотите использовать Timestampable Behavior, но с отметками времени UNIX, а не с datetime
    • И вы хотите это, не заставляя писать много конфигурационных материалов в своих моделях.
      (Я могу понять, что: меньше риска забыть одну строку где-то и ошибочные данные в БД)
  • Проект, который настроен и все
    • что означает, что вы знаете, что вы делаете с Доктриной
    • и что я не буду говорить об основах

Решение этой проблемы состояло бы в том, чтобы не использовать поведение Timestampable по умолчанию, которое поставляется с Doctrine, но другое, которое вы определите.
Это означает, что в вашей модели у вас будет что-то подобное внизу метода setTableDefinition :

 $this->actAs('MyTimestampable'); 

(Я полагаю, это может пойти и в методе setUp , кстати, может быть, это было бы реально, на самом деле)


Теперь нам нужно определить поведение MyTimestampable , поэтому оно делает то, что мы хотим.
Поскольку Doctrine's 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 класс 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
  • Наше поведение расширяет доктрину
  • И только переопределить его конфигурацию
    • Поэтому мы можем использовать его, как мы хотим, с одной строкой кода в каждой из наших моделей.

Я дам вам провести более интенсивные тесты, но я надеюсь, что это поможет!
Получайте удовольствие 🙂

Один из методов заключается в том, чтобы использовать докторантов-слушателей для создания унифицированной временной метки времени, когда запись извлекается и до ее сохранения:

 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 и преобразовывать все поля datetime 'unix _'. $ Field_name.

Удачи