Показать все даты на моделях в часовом поясе пользователя (Laravel) - PullRequest
0 голосов
/ 09 июня 2018

У меня есть пользователи часовой пояс (в таблице users DB есть столбец timezone), и я хочу отобразить все $dates атрибуты на все модели в часовом поясе пользователя, если аутентифицирован .

Я пытаюсь найти элегантный способ сделать это ... В идеале, когда в Blade что-то подобноеviews:

{{ $post->created_at }}

OR

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

... для аутентифицированных пользователей это будет автоматически в их часовых поясах.

Как бы вы справились с этим?


Я думаю о создании одной черты (например, 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) { ... }
}

Но я не уверен, хорошо это или плохо делать (чтобы создать доступ к атрибутам 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 модели, использующей эту черту?

Или, может быть, есть лучший способ справиться с этим без аксессуаров?

Ответы [ 2 ]

0 голосов
/ 09 июня 2018

Один из способов (без доступа) - использовать эту черту:

<?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 метод).

0 голосов
/ 09 июня 2018

Документация 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;    
} 
...