Website development
PHP
Laravel
31 October 2014

Локализованное форматирование даты в Laravel

From Sandbox
Сейчас я приведу очень простой способ того, как можно сделать в проекте локализованное форматирование даты на фреймворке Laravel. В конечном итоге мы получим результат, при котором получая свойство модели, к примеру, created_at (timestamp формат: 2015-10-20 19:45:56) — преобразуется в «20 Октября в 19:45». Форматирование можно будет настроить по вкусу или исходя из нужд.

Создание файла с переводами


Создаем date.php в директории app/lang/ru (если текущий язык русский). В его содержании будет формат вывода даты со временем и правильные окончания для месяцев.

<?php

return [
    'later'             => ':date в :time',
    'today'             => 'сегодня в :time',
    'yesterday'         => 'вчера в :time',
    'month_declensions' => [
        'January'   => 'Января',
        'February'  => 'Февраля',
        'March'     => 'Марта',
        'April'     => 'Апреля',
        'May'       => 'Мая',
        'June'      => 'Июня',
        'July'      => 'Июля',
        'August'    => 'Августа',
        'September' => 'Сентября',
        'October'   => 'Октября',
        'November'  => 'Ноября',
        'December'  => 'Декабря'
    ]
];


Для английского языка:
<?php

return [
    'later'             => ':date at :time',
    'today'             => 'today at :time',
    'yesterday'         => 'yesterday at :time',
    'month_declensions' => [
        'January'   => 'January',
        'February'  => 'February',
        'March'     => 'March',
        'April'     => 'April',
        'May'       => 'May',
        'June'      => 'June',
        'July'      => 'July',
        'August'    => 'August',
        'September' => 'September',
        'October'   => 'October',
        'November'  => 'November',
        'December'  => 'December'
    ]
];



Создание библиотеки


Теперь реализуем библиотеку, которая будет выполнять всю нашу логику для преобразования даты.
Создаем папку app/libraries (если ее нету) и файл DateFormat.php в папке Date, полный путь будет — app/libraries/Date/DateFormat.php.

<?php

namespace Date;

class DateFormat
{

    /**
     * данный метод написан на коленке (нужно переписать)
     */
    public static function post($time)
    {
        $timestamp = strtotime($time);
        $published = date('d.m.Y', $timestamp);

        if ($published === date('d.m.Y')) {
            return trans('date.today', ['time' => date('H:i', $timestamp)]);
        } elseif ($published === date('d.m.Y', strtotime('-1 day'))) {
            return trans('date.yesterday', ['time' => date('H:i', $timestamp)]);
        } else {
            $formatted = trans('date.later', [
                'time' => date('H:i', $timestamp),
                'date' => date('d F' . (date('Y', $timestamp) === date('Y') ? null : ' Y'), $timestamp)
            ]);

            return strtr($formatted, trans('date.month_declensions'));
        }
    }

}


Автозагрузка библиотек


Для того, чтобы все библиотеки были доступны для использования, добавим в composer.json автозагрузку классов с нашей директории app/libraries:

{
    "autoload": {
        "classmap": [
            "app/libraries"
        ]
    }
}


И обновим кэш composer'a:

composer dump-autoload


Базовая модель


Здесь можно поступить несколькими способами:
  • Создать абстрактную базовую модель и унаследоваться от нее;
  • Создать типаж (trait) и добавлять его использование в наши модели.

Я выбрал первый способ, так как он показался более практичным.

В созданном файле app/models/Model.php добавляем метод, который будет вызываться при получении свойства created_at.
Вызываться он будет автоматически, нам делать для этого ничего не нужно.

<?php

use Date\DateFormat;
use Illuminate\Database\Eloquent\Model as Eloquent;

abstract class Model extends Eloquent
{

    public function getCreatedAtAttribute($attr)
    {
        return DateFormat::post($attr);
    }

}


Данный код говорит сам за себя: при получении свойства модели created_at (название атрибута преобразуется в camelCase), верни значение обработанное методом post с помощью нашей библиотеки DateFormat. Также, можно создать методы для атрибутов updated_at, deleted_at и прочих.

Теперь можно проверить все на практике, ниже будет пример модели и контроллера для получения всех постов.

Модель app/models/Post.php:

<?php

class Post extends Model
{

    /**
     * @var string The table associated with the model.
     */
    protected $table = 'posts';
}


Контроллер app/controllers/PostController.php
<?php

class PostController extends Controller
{

    public function index()
    {
        return Post::all();
    }

}


Обратимся к нашему контроллеру (не забудьте прописать условия маршрутизации) и получим на выходе массив наших постов в json-формате, где свойство created_at будет отформатировано в необходимом языке и формате.

Реализовать такой функционал можно с помощью ServiceProvider, что будет еще более простым способом. Но данный способ нагляднее.

Буду рад услышать комментарии по коду. Хотелось бы узнать, какие есть best practices для решения подобных задач.

+4
14.2k 38
Comments 16