Сейчас я приведу очень простой способ того, как можно сделать в проекте локализованное форматирование даты на фреймворке Laravel. В конечном итоге мы получим результат, при котором получая свойство модели, к примеру, created_at (timestamp формат: 2015-10-20 19:45:56) — преобразуется в «20 Октября в 19:45». Форматирование можно будет настроить по вкусу или исходя из нужд.
Создаем date.php в директории app/lang/ru (если текущий язык русский). В его содержании будет формат вывода даты со временем и правильные окончания для месяцев.
Теперь реализуем библиотеку, которая будет выполнять всю нашу логику для преобразования даты.
Создаем папку app/libraries (если ее нету) и файл DateFormat.php в папке Date, полный путь будет — app/libraries/Date/DateFormat.php.
Для того, чтобы все библиотеки были доступны для использования, добавим в composer.json автозагрузку классов с нашей директории app/libraries:
И обновим кэш composer'a:
Здесь можно поступить несколькими способами:
Я выбрал первый способ, так как он показался более практичным.
В созданном файле app/models/Model.php добавляем метод, который будет вызываться при получении свойства created_at.
Вызываться он будет автоматически, нам делать для этого ничего не нужно.
Данный код говорит сам за себя: при получении свойства модели created_at (название атрибута преобразуется в camelCase), верни значение обработанное методом post с помощью нашей библиотеки DateFormat. Также, можно создать методы для атрибутов updated_at, deleted_at и прочих.
Теперь можно проверить все на практике, ниже будет пример модели и контроллера для получения всех постов.
Модель app/models/Post.php:
Контроллер app/controllers/PostController.php
Обратимся к нашему контроллеру (не забудьте прописать условия маршрутизации) и получим на выходе массив наших постов в json-формате, где свойство created_at будет отформатировано в необходимом языке и формате.
Реализовать такой функционал можно с помощью ServiceProvider, что будет еще более простым способом. Но данный способ нагляднее.
Буду рад услышать комментарии по коду. Хотелось бы узнать, какие есть best practices для решения подобных задач.
Создание файла с переводами
Создаем 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 для решения подобных задач.