Может войдёшь?
Черновики Написать статью Профиль

Стратегия уведомлений Eloquent

перевод

  1. 1. Цель
  2. 2. План атаки
  3. 3. Простой способ получения уведомлений
  4. 4. Стандартизованный договор
  5. 5. Наши классы уведомлений
  6. 6. Наша схема базы данных
  7. 7. Наш интерфейс администратора
  8. 8. Что за работу мы проделали?

У всех нас рано или поздно наступает момент в жизни, когда мы хотим поделиться кучей уведомлений с пользователем.

На первый взгляд это может вызвать некоторые сложности, но у меня имеется шаблон, который может решить проблему «в лоб».

Я хочу выразить отдельную благодарность Крису Фидао за оказанную мне помощь в корректировке и улучшении этой статьи. Если вас интересует больше информации о прагматичном проектировании Laravel-приложений, советую прочитать его книгу.

Примечание: Вы должны быть относительно знакомы с Illuminate / Eloquent и различными типами отношений, а также иметь некоторый опыт наследования.

Цель

Цель состоит в том, чтобы при входе пользователя в личный аккаунт, показывать ему все уведомления.

Кроме того, здесь могут существовать различные типы уведомлений. Например, может быть уведомление о новом сообщении, и уведомление о событии. Они могут иметь различные форматы.

План атаки

Для «атаки» мне нужен простой вызов чего-то типа: PHPNotification::allForUser($userId), вместо того, чтобы использовать какие-то сумасшедшие запросы каждый раз, когда я создаю новый тип уведомления. Кроме того, уведомления должны быть очень похожи: мы не хотим, чтобы уведомления, подтверждаемые пользователем, кардинально отличались от наших уведомлений писем. Для этого задания мы возьмем два типа уведомлений, использующихся на FaceBook: письма и сообщения.

Мы сделаем следующее:

  1. Создадим базовую Eloquent-модель уведомлений, которую мы будем использовать для всех будущих типов уведомлений.
  2. Реализуем некоторый образец модели уведомлений для писем и сообщений.
  3. Используем составитель шаблонов для того, чтобы добавить уведомление для каждого интерфейса.

Простой способ получения уведомлений

Чтобы выбрать наиболее простой метод получения всех уведомлений для пользователя, мы могли бы пойти немного дальше и создать репозиторий. Но это может вызвать некоторые проблемы, когда мы создаем новое уведомление для игр или какое-либо уведомление, выходящее за рамки данной реализации. С другой стороны, мы сохраним всю информацию о наших уведомлениях в JSON-формате или в сериализованном формате в нашей базе данных, но с этим немного неудобно работать в дальнейшем и простой класс уведомления должен будет знать обо всех типах уведомлений, которые будут использоваться в нашем приложении.

Вместо этого, давайте воспользуемся отношением Eloquent MorphToOne и создадим родительскую модель уведомлений, которая относится к уведомлениям нашего пользователя. Тогда мы сможем использовать магические методы, чтобы пройти все взаимодействия наших дочерних уведомлений.

PHP
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);
  }
}

Стандартизованный договор

Когда я размышлял над уведомлениями для моего пользовательского интерфейса, я подумал, что мне больше нравится интерфейс с описанием, кнопкой подтверждения и кнопкой отмены. Я не хочу, чтобы мой интерфейс производил очень много действий, поэтому я иду дальше и создаю маленький абстрактный класс, чтобы убедиться, что я следую договору, позволяющему легко расширять функционал. Здесь же мы объявляем родительскую модель уведомлений.

PHP
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');
  }
}

Наши классы уведомлений

Давайте разберем наш PHPPostNotification. Например, я хочу сказать «Джош написал что-то на вашей стене», значит должна быть ссылка на сообщение, которое нас извещает об этом. PHPMessageNotification очень похож на него, за исключением нескольких изменений, относящихся к письмам, а не к сообщениям.

PHP
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('Письмо');
  }
}

Наша схема базы данных

Хоть это и простой набросок шаблона, показывающий, как обрабатывать уведомления, я хотел бы остановиться на том, как будет выглядеть схема для базы данных для этого примера:

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

Наш интерфейс администратора

Итак, мы хотим, чтобы наши уведомления были доступны для всех наших шаблонов, включающих шаблон notificationCenter. Поэтому мы используем составитель шаблонов, чтобы быть уверенными, что мы никогда не забудем отправить уведомление в пользовательский интерфейс.

PHP
View::composer('notificationCenter', function($view)
{
  
$user Auth::user();
  
$notifications Notification::where('user_id'$user->id)->get();
  
$view->with('notifications'$notifications);
});

Теперь часть нашего шаблона notificationCenter выглядит следующим образом:

PHP
<ul>
    <legend>Уведомления</legend>
    <?php foreach ($notifications as $notification) : ?>
    <li>
        <span class="message">
            <?= $notification->message ?>
        </span>
        <div class="btn primary">
            <?= $notification->acceptLink ?>
        </div>
        <div class="btn info">
            <?= $notification->declineLink ?>
        </div>
    </li>
    <?php endforeach ?>
</ul>

Что за работу мы проделали?

В этой статье мы затронули множество тем, но есть еще и не описанный материал. Мы рассмотрели принцип создания шаблона, работающего над обработкой уведомлений в панели администратора.

  1. Мы создали родительскую модель уведомлений, которая позволяет разбирать все наши различные типы уведомлений из одного места.
  2. Мы создали договор для наших типов уведомлений, используя абстрактный класс, который именуется PHPNotifiableModel.
  3. Мы создали реализацию PHPPostNotification.
  4. Наконец, мы использовали составитель шаблонов, чтобы сделать наш шаблон notificationCenter намного проще, всегда используя выборку из уведомлений авторизованного пользователя.

Мы не рассмотрели создание наших уведомлений и их прикрепление к родительскому контейнеру уведомлений, но это похоже на отношение Polymorphic-One-To-One. Мы также не рассмотрели реализацию notifications.posts.accept и notifications.posts.decline маршрутов, хотя это уже специфика приложения. В нашем примере с письмом, accept маршрут удалит уведомление и перенаправит нас на страницу с сообщением, в то время как PHPdecline маршрут просто удалит уведомление.

Как вы считаете, полезен ли этот материал? Да Нет

Написать комментарий

Разметка: ? ?

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