Pergunta

Como uso timestamps do Unix com o comportamento da Doutrina Timestampable? Eu encontrei o seguinte snippet de código aqui, mas prefiro não adicionar manualmente em todos os lugares:

$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())));
Foi útil?

Solução

Esta é uma pergunta que pode obter uma resposta mais fácil do que eu pensava, na verdade ...

Vamos começar pelo que você tem agora:

  • uma classe modelo, que se estende Doctrine_Record
    • Vou chamar essa aula Test, para o meu (s) exemplo (s).
    • Nisso Test modelo, você deseja usar o Timestampable Comportamento, mas com timestamps Unix, e não datetime valores
    • E você quer isso sem ter que escrever muitas coisas de configuração em seus modelos.
      (Eu posso entender isso: Menos risco de esquecer uma linha em algum lugar e em dados errados no banco de dados)
  • Um projeto que está configurado e tudo
    • O que significa que você conhece coisas com doutrina
    • e que não vou falar sobre o básico

Uma solução para esse problema seria não usar o padrão Timestampable comportamento que vem com doutrina, mas outra, que você definirá.
O que significa que, em seu modelo, você terá algo assim na parte inferior de setTableDefinition método:

$this->actAs('MyTimestampable');

(Suponho que isso possa ir no setUp Método também, btw - talvez seja o lugar real, na verdade)


O que agora temos que fazer é definir isso MyTimestampable comportamento, então faz o que queremos.
Como doutrina Doctrine_Template_Timestampable Já faz o trabalho muito bem (Exceto pelo formato, é claro), nós herdaremos dele; Felizmente, isso significará menos código para escrever ;-)

Então, declaramos nossa aula de comportamento como esta:

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

Agora, vamos dar uma olhada no que Doctrine_Template_Timestampable Na verdade, na fonte de código da doutrina:

  • um pouco de configuração (os dois created_at e updated_at Campos)
  • E a linha a seguir, que registra um ouvinte:


$this->addListener(new Doctrine_Template_Listener_Timestampable($this->_options));

Vamos dar uma olhada na fonte deste; Notamos esta parte:

if ($options['type'] == 'date') {
    return date($options['format'], time());
} else if ($options['type'] == 'timestamp') {
    return date($options['format'], time());
} else {
    return time();
}

Isso significa se o tipo dos dois created_at e updated_at campos não é date nem timestamp, Doctrine_Template_Listener_Timestampable Usará automaticamente um registro de data e hora do UNIX - que conveniente!


Como você não deseja definir o type Para usar para esses campos em todos os seus modelos, modificaremos nosso MyTimestampable classe.
Lembre -se, dissemos que estava se estendendo Doctrine_Template_Timestampable, responsável pela configuração do comportamento ...

Então, substituímos essa configuração, usando um type outro que não seja date e 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)));
}

Dissemos anteriormente que nosso modelo estava agindo como MyTimestampable, e não Timestampable... Então, agora, vamos ver o resultado ;-)

Se considerarmos esta classe modelo para 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');
    }
}

Que mapeia para a seguinte tabela 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

Podemos criar duas linhas na tabela desta maneira:

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

Se verificarmos os valores no banco de dados, conseguiremos algo assim:

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)

Então, estamos bem para a criação de linhas, ao que parece ;-)


E agora, vamos buscar e atualizar a segunda linha:

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

E, de volta ao banco de dados, agora entendemos o seguinte:

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)

o updated_at o campo foi atualizado e o created_at O campo não mudou; O que parece ok também ;-)


Então, para resumir as coisas, se encaixe em alguns pontos de bala e resume um pouco:

  • Nossa classe modelo atua como nossa MyTimestampable, e não o padrão Timestampable
  • Nosso comportamento estende o único da doutrina
  • E apenas substitui sua configuração
    • Para que possamos usá -lo como queremos, com apenas uma linha de código em cada um de nossos modelos.


Vou deixar você fazer testes mais intensivos, mas espero que isso ajude!
Divirta-se :-)

Outras dicas

Um método seria usar os ouvintes da Doctorine para criar um timestamp Unix equivalente quando o registro for buscado e antes de ser salvo:

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;
    }
}

Essa pode ser a sua classe base que você se estende em qualquer coisa que precise da funcionalidade criada e atualizada_at.

Tenho certeza de que, com um pouco mais de mexer, você pode atravessar $ dados e converter todos os campos de dados 'Unix _'. $ Field_name.

Boa sorte

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top