CakePHP 3时间列获取日期 [英] CakePHP 3 time column gets date added
问题描述
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
forDATE
早期的CakePHP 3版本只有 \Cake\I18n \\ Time
。
如果只有一个单独的类才能使用时间类型,这将是一个适当的时间默认输出格式设置,但直到添加了类似的内容,您将不得不自己处理输出格式。
视图格式
这取决于你如何在你的意见中显示。您可以轻松地使用 Time
类实例
$ b的
i18nFormat()
$ b $ record ['start_time'] - > i18nFormat(
[\IntlDateFormatter :: NONE,\IntlDateFormatter SHORT]
)
或时间
helper,只显示时间部分
$ this-> Time-> i18nFormat(
/ pre>
$ record ['start_time'],
[\IntlDateFormatter :: NONE,\IntlDateFormatter :: SHORT]
)
如果烘焙会根据列的类型生成类似的代码,那么可能不会受到伤害,您可能希望 表示作为增强 。如上所述,使用额外的类(或者可能的选项)仅供时间使用的列可能值得考虑。
使用自定义时间类
如果您想要使用该对象的字符串表示形式的任何地方,而无需手动调用格式化程序,则可以使用扩展的
\\ \\ 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
forTIME
,TIMESTAMP
, andDATETIME
\Cake\I18n\Date
or\Cake\I18n\FrozenDate
forDATE
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
- Cookbook > Time > Setting the Default Locale and Format String
- Cookbook > Database Access & ORM > Database Basics > Adding Custom Types
这篇关于CakePHP 3时间列获取日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!