Сейчас я приведу очень простой способ того, как можно сделать в проекте локализованное форматирование даты на фреймворке Laravel. В конечном итоге мы получим результат, при котором получая свойство модели, к примеру, created_at (timestamp формат: 2014-10-31 10:08: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 DateDateFormat;
use IlluminateDatabaseEloquentModel 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 для решения подобных задач.
Автор: Khaperets