如何为 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.

基于此:https://laravel.com/api/5.5/Illuminate/Database/Eloquent/Concerns/HasAttributes.html#method_getAttribute

描述说:

Get a plain attribute (not a relationship).

幸运的是,它下面还有另外两个方法,称为 getRelationValuegetRelationshipFromMethod,它显示为:

Get a relationship.

Get a relationship value from a method.

分别

在您的示例中,您似乎在调用关系。

我觉得你做通用的时候应该考虑一下getter/mutator。

更新:

如果您检查代码,getAttribute 也会调用 getRelationValue 方法。不过是不得已的函数;如果 key 既不是属性也没有修改器或者是 class.

的方法

这是存根:https://github.com/laravel/framework/blob/5.5/src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php#L302

/**
 * 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'];