CakePHP 3 时间列获取添加日期
CakePHP 3 time column gets date added
我的 MySQL 数据库中有许多列定义为 "time"。也就是说,他们有时间,但没有约会。当它们被 CakePHP 3 ORM 读取时,它们被转换为 Cake\I18n\Time 对象(通过 Cake\Database\Type\TimeType class),但结果总是包含日期和时间,日期设置为当前日期。例如,如果值为“20:00:00”,debug($record['start_time'])
将生成:
object(Cake\I18n\Time) {
'time' => '2015-06-21T20:00:00+0000',
'timezone' => 'UTC',
'fixedNowTime' => false
}
当我在模板中回应它时(没有使用 setToStringFormat
),我得到类似 6/21/15 8:00 PM
的结果。当然,我可以使用 $this->Time->format
将其恢复为仅时间格式,但我需要这样做似乎很奇怪。为什么 Cake 忽略了这样一个事实,即 只是 一次,更重要的是,有没有办法让它停止?
事实是 cakePHP 将你的时间值作为时间对象执行,它扩展了碳和 dateTime,所以你得到一个包含日期的完整 dateTime 实例:(
但是您可以轻松地对您的实体执行自动设置。您只需使用此处描述的访问器和修改器:http://book.cakephp.org/3.0/en/orm/entities.html#accessors-mutators
Date/Time 值都被转换为相同的基本结构,即 DateTime
或 DateTimeImmutable
对象,因此自然地,仅日期值将添加时间值(00:00:00
),并且时间值带有日期(当前日期)。
CakePHP 将根据 SQL 数据类型使用特定的子 classes,即
\Cake\I18n\Time
或 \Cake\I18n\FrozenTime
表示 TIME
、TIMESTAMP
和 DATETIME
\Cake\I18n\Date
或 \Cake\I18n\FrozenDate
对于 DATE
在早期的 CakePHP 3 个版本中只有 \Cake\I18n\Time
.
如果有一个单独的 class 用于仅限时间的类型,那会很好,它将有一个适当的仅限时间的默认输出格式设置,但在添加类似的东西之前,你会必须自己处理输出格式。
您认为的格式
如何在您的视图中显示它取决于您。您可以轻松使用 Time
class 实例
的 i18nFormat()
方法
$record['start_time']->i18nFormat(
[\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT]
)
或 Time
助手,仅显示时间部分
$this->Time->i18nFormat(
$record['start_time'],
[\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT]
)
我猜如果 bake 会根据列的类型生成类似的代码也没什么坏处,您可能想要 suggest that as an enhancement。如前所述,为仅限时间的列使用额外的 classes(或选项)也可能值得考虑。
使用自定义时间class
如果您希望在使用对象的字符串表示形式的任何地方都有这种行为,而不必手动调用格式化程序,那么您可以使用扩展的 \Cake\I18n\Time
或 \Cake\I18n\FrozenTime
class 与覆盖 $_toStringFormat
属性,以便它相应地格式化日期。
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');
// ...
这应该是不言而喻的,映射到 TimeType
的 time
列现在将使用 App\I18n\FrozenTimeOnly
而不是默认的 Cake\I18n\Time
。
DateTimeType::$dateTimeClass
已弃用
为了解决这个问题,需要自定义数据库类型,这也很简单。
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);
}
}
应该注意的是,目前这将实例化一个 data/time class 两次,因为父构造函数也会调用 _setClassName()
,这是给定 class 将被实例化。
src/config/bootstrap.php
use App\Database\Type\TimeOnlyType;
Type::map('time', TimeOnlyType::class);
所以这会做什么,覆盖默认 time
类型映射以使用自定义 \App\Database\Type\TimeOnlyType
class,这反过来将使用 \App\I18n\TimeOnly
class 将数据库值转换为 PHP 对象时,当转换为字符串时,将使用仅时间格式。
另见
我的 MySQL 数据库中有许多列定义为 "time"。也就是说,他们有时间,但没有约会。当它们被 CakePHP 3 ORM 读取时,它们被转换为 Cake\I18n\Time 对象(通过 Cake\Database\Type\TimeType class),但结果总是包含日期和时间,日期设置为当前日期。例如,如果值为“20:00:00”,debug($record['start_time'])
将生成:
object(Cake\I18n\Time) {
'time' => '2015-06-21T20:00:00+0000',
'timezone' => 'UTC',
'fixedNowTime' => false
}
当我在模板中回应它时(没有使用 setToStringFormat
),我得到类似 6/21/15 8:00 PM
的结果。当然,我可以使用 $this->Time->format
将其恢复为仅时间格式,但我需要这样做似乎很奇怪。为什么 Cake 忽略了这样一个事实,即 只是 一次,更重要的是,有没有办法让它停止?
事实是 cakePHP 将你的时间值作为时间对象执行,它扩展了碳和 dateTime,所以你得到一个包含日期的完整 dateTime 实例:(
但是您可以轻松地对您的实体执行自动设置。您只需使用此处描述的访问器和修改器:http://book.cakephp.org/3.0/en/orm/entities.html#accessors-mutators
Date/Time 值都被转换为相同的基本结构,即 DateTime
或 DateTimeImmutable
对象,因此自然地,仅日期值将添加时间值(00:00:00
),并且时间值带有日期(当前日期)。
CakePHP 将根据 SQL 数据类型使用特定的子 classes,即
\Cake\I18n\Time
或\Cake\I18n\FrozenTime
表示TIME
、TIMESTAMP
和DATETIME
\Cake\I18n\Date
或\Cake\I18n\FrozenDate
对于DATE
在早期的 CakePHP 3 个版本中只有 \Cake\I18n\Time
.
如果有一个单独的 class 用于仅限时间的类型,那会很好,它将有一个适当的仅限时间的默认输出格式设置,但在添加类似的东西之前,你会必须自己处理输出格式。
您认为的格式
如何在您的视图中显示它取决于您。您可以轻松使用 Time
class 实例
i18nFormat()
方法
$record['start_time']->i18nFormat(
[\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT]
)
或 Time
助手,仅显示时间部分
$this->Time->i18nFormat(
$record['start_time'],
[\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT]
)
我猜如果 bake 会根据列的类型生成类似的代码也没什么坏处,您可能想要 suggest that as an enhancement。如前所述,为仅限时间的列使用额外的 classes(或选项)也可能值得考虑。
使用自定义时间class
如果您希望在使用对象的字符串表示形式的任何地方都有这种行为,而不必手动调用格式化程序,那么您可以使用扩展的 \Cake\I18n\Time
或 \Cake\I18n\FrozenTime
class 与覆盖 $_toStringFormat
属性,以便它相应地格式化日期。
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');
// ...
这应该是不言而喻的,映射到 TimeType
的 time
列现在将使用 App\I18n\FrozenTimeOnly
而不是默认的 Cake\I18n\Time
。
DateTimeType::$dateTimeClass
已弃用
为了解决这个问题,需要自定义数据库类型,这也很简单。
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);
}
}
应该注意的是,目前这将实例化一个 data/time class 两次,因为父构造函数也会调用 _setClassName()
,这是给定 class 将被实例化。
src/config/bootstrap.php
use App\Database\Type\TimeOnlyType;
Type::map('time', TimeOnlyType::class);
所以这会做什么,覆盖默认 time
类型映射以使用自定义 \App\Database\Type\TimeOnlyType
class,这反过来将使用 \App\I18n\TimeOnly
class 将数据库值转换为 PHP 对象时,当转换为字符串时,将使用仅时间格式。