CakePHP 3时间列获取日期

Gre*_*idt 3 mysql time orm date cakephp-3.0

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

object(Cake\I18n\Time) {
    'time' => '2015-06-21T20:00:00+0000',
    'timezone' => 'UTC',
    'fixedNowTime' => false
}
Run Code Online (Sandbox Code Playgroud)

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

ndm*_*ndm 8

日期/时间值都被转换为相同的基础结构,即一个DateTime或一个DateTimeImmutable对象,因此自然日期值将具有添加时间值(00:00:00),并且仅时间值带有日期(当前日期) .

CakePHP将使用特定的子类,具体取决于SQL数据类型

  • \Cake\I18n\Time\Cake\I18n\FrozenTimeTIME,TIMESTAMPDATETIME
  • \Cake\I18n\Date\Cake\I18n\FrozenDateDATE

在之前的CakePHP 3版本中,只有\Cake\I18n\Time.

如果有一个单独的类只用于时间类型会很好,它会有一个适当的仅限时间的默认输出格式,但是在添加类似的东西之前,你必须自己处理输出格式.

在您的视图中格式化

由您决定如何在您的视图中显示它.您可以轻松使用类实例的i18nFormat()方法Time

$record['start_time']->i18nFormat(
    [\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT]
)
Run Code Online (Sandbox Code Playgroud)

Time帮助者,只显示时间部分

$this->Time->i18nFormat(
    $record['start_time'],
    [\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT]
)
Run Code Online (Sandbox Code Playgroud)

猜猜如果根据列的类型生成类似的代码,它不会受到伤害,您可能想要建议作为增强.如上所述,对于仅限时间列使用其他类(或可能是选项)也可能是值得考虑的事情.

使用自定义时间类

如果您希望在使用对象的字符串表示的任何地方出现此行为,而无需手动调用格式化程序,则可以使用带有overriden 属性的扩展\Cake\I18n\Time\Cake\I18n\FrozenTime$_toStringFormat,以便相应地格式化日期.

SRC/-I18N/FrozenTimeOnly.php

namespace App\I18n;

use Cake\I18n\FrozenTime;

class FrozenTimeOnly extends FrozenTime
{
    protected static $_toStringFormat = [
        \IntlDateFormatter::NONE,
        \IntlDateFormatter::SHORT
    ];
}
Run Code Online (Sandbox Code Playgroud)

SRC /配置/ bootstrap.php中

use Cake\Database\Type\TimeType;
use App\I18n\FrozenTimeOnly;
TimeType::$dateTimeClass = FrozenTimeOnly::class;

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

这应该是自我解释的,time正在映射到的列TimeType现在将使用App\I18n\FrozenTimeOnly而不是默认值Cake\I18n\Time.

DateTimeType::$dateTimeClass 已弃用

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

SRC /数据库/类型/ TimeOnlyType.php

namespace App\Database\Type;

use App\I18n\FrozenTimeOnly;
use Cake\Database\Type\TimeType;

class TimeOnlyType extends TimeType
{
    public function __construct($name)
    {
        parent::__construct($name);
        $this->_setClassName(FrozenTimeOnly::class, \DateTimeImmutable::class);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

SRC /配置/ bootstrap.php中

use App\Database\Type\TimeOnlyType;
Type::map('time', TimeOnlyType::class);
Run Code Online (Sandbox Code Playgroud)

这样做会覆盖默认time类型映射以使用自定义\App\Database\Type\TimeOnlyType类,而自定义类\App\I18n\TimeOnly在将数据库值转换为PHP对象时将使用该类,当转换为字符串时,将使用仅时间格式.

也可以看看