Data

15 mar, 2018

Auto-adição em campos de data no Laravel com MySQL

Publicidade

Alcançamos um interessante “problema” de Laravel enquanto desenvolvíamos Oh Dear! sobre uma tabela MySQL.

Considere a seguinte migração de banco de dados para criar uma nova tabela com alguns campos de carimbo de data/hora:

Schema::create('downtime_periods', function (Blueprint $table) {
    $table->increments('id');
    $table->unsignedInteger('site_id');
    $table->foreign('site_id')->references('id')->on('sites')->onDelete('cascade');
    $table->timestamp('started_at');
    $table->timestamp('ended_at')->nullable();
    $table->timestamps();
});

Isso se transforma em uma tabela MySQL como essa:

mysql> DESCRIBE downtime_periods;
+------------+------------------+------+-----+-------------------+-----------------------------+
| Field      | Type             | Null | Key | Default           | Extra                       |
+------------+------------------+------+-----+-------------------+-----------------------------+
| id         | int(10) unsigned | NO   | PRI | NULL              | auto_increment              |
| site_id    | int(10) unsigned | NO   | MUL | NULL              |                             |
| started_at | timestamp        | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| ended_at   | timestamp        | YES  |     | NULL              |                             |
| created_at | timestamp        | YES  |     | NULL              |                             |
| updated_at | timestamp        | YES  |     | NULL              |                             |
+------------+------------------+------+-----+-------------------+-----------------------------+
6 rows in set (0.00 sec)

Percebe a coluna Extra no campo start_at? Isso foi inesperado. Em cada salvamento/modificação em uma linha, o start_at seria atualizado automaticamente para o carimbo de data/hora atual.

A correção em Laravel para evitar esse comportamento é adicionar nullable() para a migração, assim:

$table->timestamp('started_at')->nullable();

Para corrigir uma tabela já criada, remova o comportamento Extra com uma consulta SQL.

MySQL> ALTER TABLE downtime_periods
CHANGE started_at started_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP;

Mais tarde, a tabela se parece com o que você esperava:

mysql> describe downtime_periods;
+------------+------------------+------+-----+---------+----------------+
| Field      | Type             | Null | Key | Default | Extra          |
+------------+------------------+------+-----+---------+----------------+
| id         | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| site_id    | int(10) unsigned | NO   | MUL | NULL    |                |
| started_at | timestamp        | YES  |     | NULL    |                |
| ended_at   | timestamp        | YES  |     | NULL    |                |
| created_at | timestamp        | YES  |     | NULL    |                |
| updated_at | timestamp        | YES  |     | NULL    |                |
+------------+------------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)

Lição aprendida!

***

Mattias Geniar faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela Redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: https://ma.ttias.be/laravel-mysql-auto-adding-update-current_timestamp-timestamp-fields/