CakePHP 3 时间列添加了日期 [英] CakePHP 3 time column gets date added

查看:30
本文介绍了CakePHP 3 时间列添加了日期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 MySQL 数据库中将许多列定义为时间".也就是说,他们有时间,但没有约会.当它们被 CakePHP 3 ORM 读取时,它们被转换成 CakeI18nTime 对象(通过 CakeDatabaseTypeTimeType 类),但结果中总是包含日期和时间,其中日期设置为当前日期.例如,如果值为20:00:00",debug($record['start_time']) 将生成:

I have a number of columns defined in my MySQL database as "time". That is, they have a time, but not a date. When they are read by the CakePHP 3 ORM, they are being converted into CakeI18nTime objects (through the CakeDatabaseTypeTimeType class), but the result always has both a date and a time in it, with the date set to the current date. For example, if the value is "20:00:00", debug($record['start_time']) will generate:

object(CakeI18nTime) {
    'time' => '2015-06-21T20:00:00+0000',
    'timezone' => 'UTC',
    'fixedNowTime' => false
}

当我在模板中回显它时(没有使用 setToStringFormat),我得到类似 6/21/15 8:00 PM 的信息.当然,我可以使用 $this->Time->format 将它放回仅限时间的格式,但我需要这样做似乎很奇怪.为什么 Cake 无视这只是时间这一事实,更重要的是,有没有办法让它停止?

And when I echo it in a template (without having used setToStringFormat), I get something like 6/21/15 8:00 PM. Of course, I can use $this->Time->format to put it back into a time-only format, but it seems very strange that I would need to do so. Why is Cake ignoring the fact that this is just a time, and, more importantly, is there a way to make it stop?

推荐答案

日期/时间值都被强制转换为相同的基本结构,即 DateTimeDateTimeImmutable 对象,因此纯日期值自然会有一个时间添加的值 (00:00:00),并且仅时间值带有日期(当前日期).

Date/Time values are all being casted to the same base structure, that is a DateTime or DateTimeImmutable object, and so naturally date-only values will have a time value added (00:00:00), and time-only values come with a date (the current date).

CakePHP 将根据 SQL 数据类型使用特定的子类,即

CakePHP will uses specific subclasses depending on the SQL datatype, that is

  • CakeI18nTimeCakeI18nFrozenTime 用于 TIMETIMESTAMP日期时间
  • CakeI18nDateCakeI18nFrozenDate 用于 DATE
  • CakeI18nTime or CakeI18nFrozenTime for TIME, TIMESTAMP, and DATETIME
  • CakeI18nDate or CakeI18nFrozenDate for DATE

在早期的 CakePHP 3 版本中只有 CakeI18nTime.

In earlier CakePHP 3 versions there was only CakeI18nTime.

如果有一个单独的类用于仅时间类型会很好,它将具有适当的仅时间默认输出格式集,但是在添加类似的内容之前,您必须注意自己输出格式.

It would be nice if there would be a separate class for time-only types, which would have a proper time-only default output format set, but until something like that is added, you'll have to take care of the output format yourself.

如何在您的视图中显示它取决于您.您可以轻松使用Time类实例

It is up to you how to display this in your views. You can easily use the i18nFormat() method of the Time class instance

$record['start_time']->i18nFormat(
    [IntlDateFormatter::NONE, IntlDateFormatter::SHORT]
)

Time 助手,只显示时间部分

or the Time helper, to show only the time part

$this->Time->i18nFormat(
    $record['start_time'],
    [IntlDateFormatter::NONE, IntlDateFormatter::SHORT]
)

猜猜如果bake 会根据列的类型生成类似的代码不会有什么坏处,您可能想要建议将其作为改进.如前所述,为仅时间列使用额外的类(或可能的选项)也可能值得考虑.

Guess it wouldn't hurt if bake would generate similar code according to the type of column, you may want to suggest that as an enhancement. As mentioned using additional classes (or maybe options) for time-only columns may be something worth to consider too.

如果您希望在使用对象的字符串表示的任何地方都有这种行为,而不必手动调用格式化程序,那么您可以使用扩展的 CakeI18nTime 或具有覆盖 $_toStringFormat 属性的 CakeI18nFrozenTime 类,以便相应地格式化日期.

If you'd wanted this behavior everywhere where the string representation of the object is being used, without having to manually invoke the formatter, then you could make use of an extended CakeI18nTime or CakeI18nFrozenTime class with an overriden $_toStringFormat property, so that it formats the date accordingly.

src/I18n/FrozenTimeOnly.php

namespace AppI18n;

use CakeI18nFrozenTime;

class FrozenTimeOnly extends FrozenTime
{
    protected static $_toStringFormat = [
        IntlDateFormatter::NONE,
        IntlDateFormatter::SHORT
    ];
}

src/config/bootstrap.php

use CakeDatabaseTypeTimeType;
use AppI18nFrozenTimeOnly;
TimeType::$dateTimeClass = FrozenTimeOnly::class;

// remove the default `useImmutable()` call, you may however
// want to keep further calls for formatting and stuff
Type::build('time'); 
// ...

这应该是不言自明的,映射到 TimeTypetime 列现在将使用 AppI18nFrozenTimeOnly 代替默认CakeI18nTime.

This should pretty much self-explantory, time columns that are being mapped to TimeType, will now use AppI18nFrozenTimeOnly instead of the default CakeI18nTime.

为了解决这个问题,需要一个自定义的数据库类型,这也很简单.

In order to cope with that, a custom database type will be required, which is rather simple too.

src/Database/Type/TimeOnlyType.php

namespace AppDatabaseType;

use AppI18nFrozenTimeOnly;
use CakeDatabaseTypeTimeType;

class TimeOnlyType extends TimeType
{
    public function __construct($name)
    {
        parent::__construct($name);
        $this->_setClassName(FrozenTimeOnly::class, DateTimeImmutable::class);
    }
}

应该注意,目前这将实例化一个数据/时间类两次,因为父构造函数也会调用 _setClassName(),这是给定类的实例将被实例化的地方.

It should be note that currently this will instantiate a data/time class twice, as the parent constructor will invoke _setClassName() too, which is where an instance of the given class will be instantiated.

src/config/bootstrap.php

use AppDatabaseTypeTimeOnlyType;
Type::map('time', TimeOnlyType::class);

所以这会做的是覆盖默认的 time 类型映射以使用自定义的 AppDatabaseTypeTimeOnlyType 类,而后者将使用AppI18nTimeOnly 将数据库值转换为 PHP 对象时的类,当转换为字符串时,将使用仅时间格式.

So what this will do, is override the default time type mapping to use the custom AppDatabaseTypeTimeOnlyType class, which in turn will use the AppI18nTimeOnly class when converting database values to PHP objects, which when converted to a string, will use the time-only format.

这篇关于CakePHP 3 时间列添加了日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆