在用户的时区(Laravel)中显示模型上的所有日期

Per*_*ika 6 php laravel php-carbon laravel-5

我存储了用户时区(数据库表中有timezoneusers),如果经过身份验证,我想显示用户时区中所有模型的所有 $dates属性。

我试图找到一种优雅的方式来做到这一点......理想情况下,当 Blade 视图中有这样的东西时:

{{ $post->created_at }}

OR

{{ $post->created_at->format('h:i:s A') }}
Run Code Online (Sandbox Code Playgroud)

...对于经过身份验证的用户,它将自动在他们的时区中。

你会如何处理这件事?


我正在考虑创建一个特质(例如app/Traits/UserTimezoneAware.php)和地点有访问器,将简单地返回Carbon::createFromFormat('Y-m-d H:i:s', $value)->timezone(auth()->user()->timezone)如果当前用户进行身份验证。例如:

<?php

namespace App\Traits;

use Carbon\Carbon;

trait UserTimezoneAware
{
    /**
     * Get the created_at in the user's timezone.
     *
     * @param $value
     * @return mixed
     */
    public function getCreatedAtAttribute($value)
    {
        if (auth()->check()) {
            return Carbon::createFromFormat('Y-m-d H:i:s', $value)->timezone(auth()->user()->timezone);
        }

        return Carbon::createFromFormat('Y-m-d H:i:s', $value);
    }

    /**
     * Get the updated_at in the user's timezone.
     *
     * @param $value
     * @return mixed
     */
    public function getUpdatedAtAttribute($value) { ... }
}
Run Code Online (Sandbox Code Playgroud)

但我不确定这样做是好是坏(为 Laravel 的$dates属性创建这些访问器)?

此外,模型将具有在数组中指定的不同属性$dates:例如,User模型可以具有:

/**
 * The attributes that should be mutated to dates.
 *
 * @var array
 */
protected $dates = [
    'created_at',
    'updated_at',
    'last_login_at'
];
Run Code Online (Sandbox Code Playgroud)

Post模型可以有:

protected $dates = [
    'created_at',
    'updated_at',
    'approved_at',
    'deleted_at'
];
Run Code Online (Sandbox Code Playgroud)

是否可以根据$dates使用该特征的模型数组中指定的属性在特征中动态创建访问器?

或者也许有更好的方法来处理这个问题,而无需访问器?

Per*_*ika 5

一种方法(没有访问器)是使用此特征:

<?php

namespace App\Traits;

use DateTimeInterface;
use Illuminate\Support\Carbon;

trait UserTimezoneAware
{
    /**
     * Return a timestamp as DateTime object.
     *
     * @param  mixed  $value
     * @return \Illuminate\Support\Carbon
     */
    protected function asDateTime($value)
    {
        $timezone = auth()->check() ? auth()->user()->timezone : config('app.timezone');

        if ($value instanceof Carbon) {
            return $value->timezone($timezone);
        }

        if ($value instanceof DateTimeInterface) {
            return new Carbon(
                $value->format('Y-m-d H:i:s.u'), $timezone
            );
        }

        if (is_numeric($value)) {
            return Carbon::createFromTimestamp($value)->timezone($timezone);
        }

        if ($this->isStandardDateFormat($value)) {
            return Carbon::createFromFormat('Y-m-d', $value)->startOfDay()->timezone($timezone);
        }

        return Carbon::createFromFormat(
            str_replace('.v', '.u', $this->getDateFormat()), $value
        )->timezone($timezone);
    }
}
Run Code Online (Sandbox Code Playgroud)

当使用这个特征时,我们会覆盖特征asDateTime($value)中定义的Concerns\HasAttributes(在 )中使用Illuminate\Database\Eloquent\Model

这似乎工作正常,我还没有遇到任何问题。

但我不确定这样做时(当使用这个覆盖asDateTime方法的特征时)是否存在任何风险或潜在问题。