{{TOC}} У всех нас рано или поздно наступает момент в жизни, когда мы хотим поделиться кучей уведомлений с пользователем. На первый взгляд это может вызвать некоторые сложности, но у меня имеется шаблон, который может решить проблему "в лоб". //Я хочу выразить отдельную благодарность ((http://fideloper.com/ Крису Фидао)) за оказанную мне помощь в корректировке и улучшении этой статьи. Если вас интересует больше информации о прагматичном проектировании Laravel-приложений, советую прочитать ((https://leanpub.com/implementinglaravel его книгу)).// **Примечание: Вы должны быть относительно знакомы с Illuminate / ((док4:eloquent Eloquent)) и различными типами отношений, а также иметь некоторый опыт наследования.** == Цель == Цель состоит в том, чтобы при входе пользователя в личный аккаунт, показывать ему все уведомления. Кроме того, здесь могут существовать различные типы уведомлений. Например, может быть уведомление о новом сообщении, и уведомление о событии. Они могут иметь различные форматы. == План атаки == Для "атаки" мне нужен простой вызов чего-то типа: %%Notification::allForUser($userId)%%, вместо того, чтобы использовать какие-то сумасшедшие запросы каждый раз, когда я создаю новый тип уведомления. Кроме того, уведомления должны быть очень похожи: мы не хотим, чтобы уведомления, подтверждаемые пользователем, кардинально отличались от наших уведомлений писем. Для этого задания мы возьмем два типа уведомлений, использующихся на FaceBook: письма и сообщения. Мы сделаем следующее: 1. Создадим базовую Eloquent-модель уведомлений, которую мы будем использовать для всех будущих типов уведомлений. 2. Реализуем некоторый образец модели уведомлений для писем и сообщений. 3. Используем ((док4:responses#составител+и))ь шаблонов для того, чтобы добавить уведомление для каждого интерфейса. == Простой способ получения уведомлений == Чтобы выбрать наиболее простой метод получения всех уведомлений для пользователя, мы могли бы пойти немного дальше и создать репозиторий. Но это может вызвать некоторые проблемы, когда мы создаем новое уведомление для игр или какое-либо уведомление, выходящее за рамки данной реализации. С другой стороны, мы сохраним всю информацию о наших уведомлениях в ((ВП:JSON))-формате или в сериализованном формате в нашей базе данных, но с этим немного неудобно работать в дальнейшем и простой класс уведомления должен будет знать обо всех типах уведомлений, которые будут использоваться в нашем приложении. Вместо этого, давайте воспользуемся отношением Eloquent //MorphToOne// и создадим родительскую модель уведомлений, которая относится к уведомлениям нашего пользователя. Тогда мы сможем использовать магические методы, чтобы пройти все взаимодействия наших дочерних уведомлений. %% class Notification extends Eloquent { public function notification() { return $this->morphTo(); } public function user() { return $this->belongsTo('User'); } public function __get($key) { // Перед передачей значения дальше по цепочке, мы должны // проверить, существует ли допустимое значение return parent::__get($key) ?: $this->notification->__get($key); } } %% == Стандартизованный договор == Когда я размышлял над уведомлениями для моего пользовательского интерфейса, я подумал, что мне больше нравится интерфейс с описанием, кнопкой подтверждения и кнопкой отмены. Я не хочу, чтобы мой интерфейс производил очень много действий, поэтому я иду дальше и создаю маленький абстрактный класс, чтобы убедиться, что я следую договору, позволяющему легко расширять функционал. Здесь же мы объявляем родительскую модель уведомлений. %% namespace Notifications; abstract class NotifiableModel extends \Eloquent { // Вернет сообщение, которое мы хотим // показать в нашем уведомлении abstract public function getMessageAttribute(); // Вернет ссылку на маршрут, которая // обрабатывает успешный ответ на уведомление abstract public function getAcceptLinkAttribute(); // Вернет ссылку на маршрут, которая // обрабатывает отрицательный ответ на уведомление abstract public function getDeclineLinkAttribute(); // Дает нам возможность ссылаться на // родительскую модель уведомлений public function notification() { return $this->morphOne('Notification'); } } %% == Наши классы уведомлений == Давайте разберем наш %%PostNotification%%. Например, я хочу сказать "Джош написал что-то на вашей стене", значит должна быть ссылка на сообщение, которое нас извещает об этом. %%MessageNotification%% очень похож на него, за исключением нескольких изменений, относящихся к письмам, а не к сообщениям. %% namespace Notifications; class PostNotification extends NotifiableModel { // Я выбираю префикс к таблицам уведомлений // чтобы имитировать ресурсы, на которые они указывают. protected $table = 'notifications_posts'; public function getMessageAttribute() { // Предположим, что наше письмо возвращает // нам имя пользователя $username = $this->post->sender->name; return "{$username} оставил письмо на вашей стене"; } public function getAcceptLinkAttribute() { // Этот маршрут обрабатывает удаление // уведомления и переадресует нас на страницу с сообщением $route = 'notifications.posts.accept'; $title = 'Панель сообщения'; $parameters = array( $this->getAttribute('id') ); return link_to_route($route, $title, $parameters); } public function getDeclineLinkAttribute() { // Этот маршрут обрабатывает удаление // уведомления и переводит нас обратно // на страницу, где мы находились ранее $route = 'notifications.posts.decline'; $title = 'Отменить'; $parameters = array( $this->getAttribute('id') ); return link_to_route($route, $title, $parameters); } // Связь с сообщением для уведомления public function post() { return $this->belongsTo('Письмо'); } } %% == Наша схема базы данных == Хоть это и простой набросок шаблона, показывающий, как обрабатывать уведомления, я хотел бы остановиться на том, как будет выглядеть схема для базы данных для этого примера: %%(t) notifications id - integer notification_id - integer notification_type - string timestamps notifications_posts id - integer post_id - integer timestamps notifications_messages id - integer message_id - integer timestamps %% == Наш интерфейс администратора == Итак, мы хотим, чтобы наши уведомления были доступны для всех наших шаблонов, включающих шаблон %%(t)notificationCenter%%. Поэтому мы используем ((http://laravel.com/docs/responses#view-composers составитель шаблонов)), чтобы быть уверенными, что мы никогда не забудем отправить уведомление в пользовательский интерфейс. %% View::composer('notificationCenter', function($view) { $user = Auth::user(); $notifications = Notification::where('user_id', $user->id)->get(); $view->with('notifications', $notifications); }); %% Теперь часть нашего шаблона %%(t)notificationCenter%% выглядит следующим образом: %%