CakePHP 3时间列获取日期 [英] CakePHP 3 time column gets date added

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

问题描述

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

 对象(Cake\I18n\Time){
'time'=> '2015-06-21T20:00:00 + 0000',
'timezone'=> 'UTC',
'fixedNowTime'=> false
}

当我在一个模板中回显它(没有使用 setToStringFormat ),我得到的东西像$ code> 6/21/15 8:00 PM 。当然,我可以使用 $ this-> Time->格式将其重新设置为只有时间的格式,但是看起来很奇怪,我需要这样做。为什么蛋糕忽略了这个事实,这只是一个时间,更重要的是有办法让它停止吗?

解决方案

日期/时间值都被转换为相同的基础结构,即 DateTime DateTimeImmutable 对象,所以自然的date-only值会添加时间值( 00:00:00 ), time-only值带有日期(当前日期)。



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




  • \Cake\I18n\Time \Cake\I18n\\ TIME TIMESTAMP DATETIME code>

  • \Cake\I18n\Date \Cake\ I18n\FrozenDate for DATE



早期的CakePHP 3版本只有 \Cake\I18n \\ Time



如果只有一个单独的类才能使用时间类型,这将是一个适当的时间默认输出格式设置,但直到添加了类似的内容,您将不得不自己处理输出格式。



视图格式



这取决于你如何在你的意见中显示。您可以轻松地使用 Time 类实例


$ b的 i18nFormat() $ b

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

时间 helper,只显示时间部分

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

/ pre>

如果烘焙会根据列的类型生成类似的代码,那么可能不会受到伤害,您可能希望 表示作为增强 。如上所述,使用额外的类(或者可能的选项)仅供时间使用的列可能值得考虑。



使用自定义时间类



如果您想要使用该对象的字符串表示形式的任何地方,而无需手动调用格式化程序,则可以使用扩展的 \\ \\ Cake\I18n\Time \Cake\I18n\FrozenTime 具有覆盖 $ _ toStringFormat的类属性,以便相应地格式化日期。



src / I18n / FrozenTimeOnly.php

 命名空间App \I18n; 

使用Cake \I18n\FrozenTime;

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

src / config / bootstrap.php p>

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

//删除默认的`useImmutable()`调用,但是可以
//要进一步调用格式化和填充
Type :: build('time' );
// ...

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



DateTimeType :: $ dateTimeClass 已被弃用



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



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

 命名空间App \Database \Type; 

使用App \I18n\FrozenTimeOnly;
使用CakeDirectory

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

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



src / config / bootstrap.php

 使用App \Database\Type\TimeOnlyType; 
Type :: map('time',TimeOnlyType :: class);

所以这样做会覆盖默认的时间类型映射使用自定义的 \App\Database\Type\TimeOnlyType 类,这反过来将使用 \将数据库值转换为PHP对象时,App \I18n\TimeOnly 类将转换为字符串,将使用时间格式。



另见




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 Cake\I18n\Time objects (through the Cake\Database\Type\TimeType 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(Cake\I18n\Time) {
    'time' => '2015-06-21T20:00:00+0000',
    'timezone' => 'UTC',
    'fixedNowTime' => false
}

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?

解决方案

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 will uses specific subclasses depending on the SQL datatype, that is

  • \Cake\I18n\Time or \Cake\I18n\FrozenTime for TIME, TIMESTAMP, and DATETIME
  • \Cake\I18n\Date or \Cake\I18n\FrozenDate for DATE

In earlier CakePHP 3 versions there was only \Cake\I18n\Time.

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.

Format in your views

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]
)

or the Time helper, to show only the time part

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

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.

Use a custom time class

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 \Cake\I18n\Time or \Cake\I18n\FrozenTime class with an overriden $_toStringFormat property, so that it formats the date accordingly.

src/I18n/FrozenTimeOnly.php

namespace App\I18n;

use Cake\I18n\FrozenTime;

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

src/config/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'); 
// ...

This should pretty much self-explantory, time columns that are being mapped to TimeType, will now use App\I18n\FrozenTimeOnly instead of the default Cake\I18n\Time.

DateTimeType::$dateTimeClass is deprecated

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

src/Database/Type/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);
    }
}

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 App\Database\Type\TimeOnlyType;
Type::map('time', TimeOnlyType::class);

So what this will do, is override the default time type mapping to use the custom \App\Database\Type\TimeOnlyType class, which in turn will use the \App\I18n\TimeOnly class when converting database values to PHP objects, which when converted to a string, will use the time-only format.

See also

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

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