Laravel时间戳显示毫秒

时间:2015-07-05 04:11:08

标签: php mysql laravel laravel-5

我需要在laravel应用程序上以高精度存储updated_at时间戳,格式为" m-d-Y H:i:s.u" (包括毫秒)

根据laravel文档,我可以通过在类上设置$ dateFormat属性来自定义日期格式,但是......

主要问题是,当我使用 $ table-> nullableTimestamps()时,Laravel的架构生成器在数据库中添加了一列timestamp类型,并且根据mysql文档,类型TIMESTAMP只允许精度达到几秒钟。

关于如何实现这一目标的任何想法?

2 个答案:

答案 0 :(得分:10)

您不能这样做,因为PHP PDO驱动程序不支持时间戳中的小数秒。解决方法是选择时间戳作为字符串,这样PDO驱动程序就不会知道它真正的时间戳,只需执行// override to include micro seconds when dates are put into mysql. protected function getDateFormat() { return 'Y-m-d H:i:s.u'; } // override to include micro seconds in the created Carbon. public function freshTimestamp() { $microtime = microtime(true); $milliseconds = sprintf("%03d", ($microtime - floor($microtime)) * 1000); return date('Y-m-d H:i:s.'. $milliseconds, $microtime).""; } 但这意味着您无法使用默认选择因此,查询变成了真正的痛苦。您还需要在模型上覆盖其他几个与时间戳相关的方法。

DB::statement("ALTER TABLE `$tableName` ADD COLUMN created_at TIMESTAMP(3) NULL");

最后在你的迁移而不是nullableTimestamps中,在Schema回调之外做:

{{1}}

请注意,此示例适用于3个小数位,但如果您愿意,最多可以有6个,通过在两个位置更改3到6,在alter table和sprintf中调整乘数* 1000到1000000为6。

希望有一天PHP PDO会更新以解决这个问题,但它已经超过5年了,并且没有改变,所以我没有希望。如果您对详细信息感兴趣,请参阅此错误报告: enter image description here 我发现这个其他答案中的链接可能有助于您更好地理解该问题: http://grokbase.com/t/php/php-bugs/11524dvh68/php-bug-bug-54648-new-pdo-forces-format-of-datetime-fields

PHP最近确实显示了它的年龄,我认为这个问题是考虑转向更现代的Node.js的原因之一。

答案 1 :(得分:2)

根据malhal's answer,我能够将小数时间戳读数设为here。为方便起见,在这里贴上答案:

class BaseModel extends Model
{
    protected $dateFormat = 'Y-m-d\TH:i:s.u';

    protected function asDateTime($value)
    {
        try {
            return parent::asDateTime($value);
        } catch (\InvalidArgumentException $e) {
            return parent::asDateTime(new \DateTimeImmutable($value));
        }
    }

    public function newQuery()
    {
        $query = parent::newQuery();

        if($this->usesTimestamps()) {
            $table = $this->getTable();
            $column = $this->getDeletedAtColumn();

            $query->addSelect(DB::raw("concat($table.$column) as $column"));
        }

        return $query;
    }
}

这里有很多内容,因为它获取了应用范围的查询,然后将updated_at列的选择添加到结尾,稍后在Laravel从查询中保存模型时覆盖任何先前加载的updated_at列。对于一个丑陋的黑客,它第一次出奇的好。

时间戳在内部存储为Laravel中的Carbon

dd(MyModel->first()->updated_at->format('Y-m-d H:i:s.u'));

输出:

2017-04-14 22:37:47.426131

还要确保运行迁移以将列转换为小数时间戳。微秒级精度将时间戳的大小从4个字节增加到7个字节,但这是2017年,不要让你通过选择毫秒精度来节省一两个字节,以后你发现自己提供过时的缓存条目时会花一大笔钱:

\DB::statement("ALTER TABLE my_table MODIFY updated_at TIMESTAMP(6) NULL DEFAULT NULL");

遗憾的是,我还没有找到修改迁移模式timestamps()功能的方法来执行此操作。