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

时间:2018-06-08 21:16:26

标签: php laravel laravel-5 php-carbon

我已存储用户timezonetimezone数据库表中有users列),我想显示所有 $dates用户时区中所有型号的属性,如果经过身份验证

我正试图找到一种优雅的方法来做到这一点......理想情况下,当Blade视图中存在类似的内容时:

{{ $post->created_at }}

OR

{{ $post->created_at->format('h:i:s A') }}

...对于经过身份验证的用户,它会自动进入他们的时区。

你会如何处理?

我正在考虑创建一个特征(例如,app/Traits/UserTimezoneAware.php)并放置accessors,如果当前用户经过身份验证,则会返回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) { ... }
}

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

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

/**
 * The attributes that should be mutated to dates.
 *
 * @var array
 */
protected $dates = [
    'created_at',
    'updated_at',
    'last_login_at'
];

Post模型可以有:

protected $dates = [
    'created_at',
    'updated_at',
    'approved_at',
    'deleted_at'
];

是否可以基于使用该特征的模型的$dates数组中指定的attirbute动态在trait中创建访问器?

或者可能有更好的方法来处理这个,没有访问者?

2 个答案:

答案 0 :(得分:1)

一种方式(没有访问者)是使用这个特性:

<?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);
    }
}

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

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

但是我不确定在执行此操作时是否存在任何风险或潜在问题(使用此特征时会覆盖asDateTime方法)。

答案 1 :(得分:0)

文档https://laravel.com/docs/5.5/eloquent-mutators#date-mutators

class Flight extends Model
{
    /**
     * The storage format of the model's date columns.
     *
     * @var string
     */
    protected $dateFormat = 'U';
}

或查看https://laravel.com/docs/5.5/eloquent-mutators#attribute-casting

class User extends Model
{
    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
       'created_at' => 'datetime:Y-m-d' // or other format
    ];
}

使其以动态方式更改格式您的模型添加此方法

public function setCast($attribute, $format) 
{
    $this->casts[$attribute] = $format;    
}