Как использовать временные метки 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.
Удачи