我已存储用户timezone(timezone
数据库表中有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中创建访问器?
或者可能有更好的方法来处理这个,没有访问者?
答案 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;
}