Как глобально трактовать все метки времени Eloquent, включая часовой пояс - PullRequest
0 голосов
/ 18 января 2020

У меня есть приложение Laravel, и я просто переключаюсь на timestampTz и timestampsTz при каждой миграции. Как только я запустил php artisan migrate, я сразу же столкнулся с «Трейлинг-данными» с проблемами с Carbon из-за несоответствия формата даты, вызванного изменением.

Я не хочу добавлять $dateFormat свойство для каждой модели, которую я создаю, когда у меня нет намерения когда-либо использовать столбцы отметок времени без часового пояса. Я также не хочу вводить черту или создавать новый суперкласс, который расширяет модель Eloquent, которую я затем должен добавить к каждой модели, которая у меня уже есть (и те, которые я сгенерирую в будущем).

Есть ли Можно ли как-нибудь избежать всего этого и просто обработать все поля меток времени так, как если бы у них всех были часовые пояса?

1 Ответ

1 голос
/ 18 января 2020

Это легко сделать в Laravel 6, создав новый класс грамматики Illuminate и переопределив метод getDateFormat, который используется как запасной , если в модели отсутствует свойство dateFormat .

Загляните внутрь vendor/laravel/framework/src/Illuminate/Database/Query/Grammars. Вашему классу нужно будет расширить один из классов грамматики c, определяемых вендором, в зависимости от того, к какой базе данных вы подключаетесь. Для этого примера я буду расширять PostgresGrammar. Настройте app/Providers/AppServiceProvider.php следующим образом:

use Illuminate\Support\Facades\DB;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     * @throws \Doctrine\DBAL\DBALException
     */
    public function register()
    {
        // ...

        $conn = DB::connection(DB::getDefaultConnection());
        $platform = $conn->getDoctrineConnection()->getDatabasePlatform();
        $conn->setQueryGrammar(new class($platform->getDateTimeTzFormatString()) extends PostgresGrammar {
            protected $date_format;

            public function __construct(string $date_format)
            {
                $this->date_format = $date_format;
            }

            public function getDateFormat()
            {
                return $this->date_format;
            }
        });
    }
}

Это заменит исходную грамматику запроса другой, которая позволит нам принять строку формата даты. Анонимный класс используется, чтобы избежать необходимости создавать отдельный файл для этой небольшой функциональности, но вы можете переместить его в свой собственный файл для удобства чтения. Анонимному классу передается значение $platform->getDateTimeTzFormatString() в качестве единственного аргумента конструктора, который затем сохраняется для использования методом getDateFormat.

После этого изменения любые ошибки завершающих данных должны быть навсегда устранены. Просто убедитесь, что вы используете timestampTz и timestampsTz при каждой дальнейшей миграции. Сторонние библиотеки обычно позволяют публиковать sh любые миграции, связанные с ними, позволяя настраивать их по мере необходимости.

...