如何为 Laravel 中的日期时间创建一个通用的 getter/mutator?
How to create a universal getter/mutator for datetimes in Laravel?
我创建了一个,我认为它有效:
<?php
namespace App\Traits;
use Carbon\Carbon;
trait FormatDates
{
public function setAttribute($key, $value)
{
parent::setAttribute($key, $value);
if (strtotime($value))
$this->attributes[$key] = Carbon::parse($value);
}
}
但是调用相关模型时出现问题。例如,如果您有一个 Article 和 Tag 模型,并且您想要像这样获取所有标签:
$article->tags
它 returns null
因为那个 getter 突变体。
如何解决这个问题?
2017 年 11 月 17 日更新
我找到了解决问题的方法。在语言环境中显示日期的最佳方式是使用此函数:
\Carbon\Carbon::setToStringFormat("d.m.Y H:i");
只需创建一个服务提供者或中间件,它就会以您想要的格式显示所有 $dates。没有必要做一个getter.
描述说:
Get a plain attribute (not a relationship).
幸运的是,它下面还有另外两个方法,称为 getRelationValue 和 getRelationshipFromMethod,它显示为:
Get a relationship.
Get a relationship value from a method.
分别
在您的示例中,您似乎在调用关系。
我觉得你做通用的时候应该考虑一下getter/mutator。
更新:
如果您检查代码,getAttribute
也会调用 getRelationValue
方法。不过是不得已的函数;如果 key 既不是属性也没有修改器或者是 class.
的方法
/**
* Get an attribute from the model.
*
* @param string $key
* @return mixed
*/
public function getAttribute($key)
{
if (! $key) {
return;
}
// If the attribute exists in the attribute array or has a "get" mutator we will
// get the attribute's value. Otherwise, we will proceed as if the developers
// are asking for a relationship's value. This covers both types of values.
if (array_key_exists($key, $this->attributes) ||
$this->hasGetMutator($key)) {
return $this->getAttributeValue($key);
}
// Here we will determine if the model base class itself contains this given key
// since we don't want to treat any of those methods as relationships because
// they are all intended as helper methods and none of these are relations.
if (method_exists(self::class, $key)) {
return;
}
return $this->getRelationValue($key);
}
另一个更新
由于您更改了问题:
您可以只将属性名称放入 $casts
或 $dates
数组(在您的 Model 中),这样 Laravel 会自动转换它访问它时进入 Carbon
实例,如下所示:
class Article extends Model {
...
protected $dates = ['some_date_attribute`];
或与$casts
...
protected $casts = ['some_date_attributes' => 'date'];
你真的可以避免这个,它已经存在了!
在模型上 Class 你可以做:
protected $dates = ['nameOfTheDateOrTimestampTypeField','nameOfAnotherOne'];
我创建了一个,我认为它有效:
<?php
namespace App\Traits;
use Carbon\Carbon;
trait FormatDates
{
public function setAttribute($key, $value)
{
parent::setAttribute($key, $value);
if (strtotime($value))
$this->attributes[$key] = Carbon::parse($value);
}
}
但是调用相关模型时出现问题。例如,如果您有一个 Article 和 Tag 模型,并且您想要像这样获取所有标签:
$article->tags
它 returns null
因为那个 getter 突变体。
如何解决这个问题?
2017 年 11 月 17 日更新
我找到了解决问题的方法。在语言环境中显示日期的最佳方式是使用此函数:
\Carbon\Carbon::setToStringFormat("d.m.Y H:i");
只需创建一个服务提供者或中间件,它就会以您想要的格式显示所有 $dates。没有必要做一个getter.
描述说:
Get a plain attribute (not a relationship).
幸运的是,它下面还有另外两个方法,称为 getRelationValue 和 getRelationshipFromMethod,它显示为:
Get a relationship.
Get a relationship value from a method.
分别
在您的示例中,您似乎在调用关系。
我觉得你做通用的时候应该考虑一下getter/mutator。
更新:
如果您检查代码,getAttribute
也会调用 getRelationValue
方法。不过是不得已的函数;如果 key 既不是属性也没有修改器或者是 class.
/**
* Get an attribute from the model.
*
* @param string $key
* @return mixed
*/
public function getAttribute($key)
{
if (! $key) {
return;
}
// If the attribute exists in the attribute array or has a "get" mutator we will
// get the attribute's value. Otherwise, we will proceed as if the developers
// are asking for a relationship's value. This covers both types of values.
if (array_key_exists($key, $this->attributes) ||
$this->hasGetMutator($key)) {
return $this->getAttributeValue($key);
}
// Here we will determine if the model base class itself contains this given key
// since we don't want to treat any of those methods as relationships because
// they are all intended as helper methods and none of these are relations.
if (method_exists(self::class, $key)) {
return;
}
return $this->getRelationValue($key);
}
另一个更新
由于您更改了问题:
您可以只将属性名称放入 $casts
或 $dates
数组(在您的 Model 中),这样 Laravel 会自动转换它访问它时进入 Carbon
实例,如下所示:
class Article extends Model {
...
protected $dates = ['some_date_attribute`];
或与$casts
...
protected $casts = ['some_date_attributes' => 'date'];
你真的可以避免这个,它已经存在了!
在模型上 Class 你可以做:
protected $dates = ['nameOfTheDateOrTimestampTypeField','nameOfAnotherOne'];