Порождение событий, cqrs и laravel

Введение

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

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

Наблюдатели моделей в Laravel

13.07.2018 19:35 |
Laravel

Сразу к практике — посмотрим где и как можно использовать наблюдателей.

Итак, предположим у нас есть модель категорий с несколькими свойствами:

  • названием
  • так называемым , т.е. псевдонимом для url, то бишь адрес в строке браузера будет выглядеть как , где  — и есть тот самый псевдоним
  • булевым , которое указывает, опубликована ли данная категория

Если все поля прописаны в формах создания новой и обновления существующей категорий, то соответствующие методы в моём контроллере выглядели бы примерно  так:

(валидацию в данном случае опускаю, ну а если есть желание, на эту тему есть отдельная статья) 

Но штука в том, что — это всего-навсего преобразованное к нижнему регистру название категории, в котором подчищены «левые» символы, а пробелы и подчеркивания преобразованы в дефисы. Поэтому не вижу смысла добавлять в форму поле пседовнима, и тем более, заставлять пользователей думать, как его заполнять. И всё же каким-то образом псевдониму надо присвоить значение — вот и проблема, которую помогут решить наблюдатели.

Для начала с помощью консоли создадим наблюдателя и сразу укажем модель, события которой надо прослушивать:

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

Напомню, — это функция-хэлпер в Laravel, которая из строки делает пседовним. Причём не проблема, если строка будет на русском — кириллица будет преобразована в латиницу.

Осталось зарегистрировать наблюдателя. Для этого можно создать отдельного поставщика услуг, но сейчас обойдёмся без него — пропишем необходимый код в :

Бум! Проблема решена.

Однако рано говорить стоп, зацепим ещё поле . Предположим, что это чекбокс, а как мы знаем, если чекбокс не отмечен, то и в реквесте его не будет. Другими словами, если категория опубликована, а мы захотим снять её с публикации и во время редактирования формы уберём галочку с чекбокса — поле в базе данных не обновится. Есть разные методы борьбы с этим явлением, как, например, создание в форме скрытого поля и т.д. Но коль уж у нас есть наблюдатель, пусть поработает и тут. Вернёмся к методу , и хотя «каждый такой метод получает модель в качестве единственного аргумента», нас это не испугает — достанем реквест и там:

Готово.

Да, пример простой, но всё же — минимум кода — и всё работает, как часы. Лаконично, легко читаемо и понятно, как и всегда в Laravel. 

Вставка и изменение моделей

Для создания новой записи в БД нужно создать экземпляр модели, задать атрибуты модели и вызовать метод save:

В этом примере присвоено значение параметра name из входящего HTTP-запроса атрибуту name экземпляра модели App\Flight. При вызове метода save запись будет вставлена в таблицу. Отметки времени created_at и updated_at будут автоматически установлены при вызове save, поэтому их не нужно задавать вручную.

Метод save можно использовать и для изменения существующей модели в БД. Для изменения модели нужно получить её, изменить необходимые атрибуты и вызвать метод save. Отметка времени updated_at будет установлена автоматически:

Массовые изменения

Метод update ожидает массив пар столбец/значение, обозначающий, какие столбцы необходимо изменить.

При использовании массовых изменений Eloquent для изменяемых моделей не будут выбрасываться события saved и updated. Это происходит потому, что на самом деле модели вообще не извлекаются при массовом изменении.

Массовое назначение

Можно использовать метод create для создания и сохранения модели одной строкой. Метод вернёт добавленную модель. Однако перед этим нужно определить либо свойство fillable, либо guarded в классе модели, так как все модели Eloquent изначально защищены от массового заполнения.

Для использования данного метода необходимо в модели указать какие поля можно сохранять:

Использование метода create. Этот метод вернет ключ новой записи:

Если уже есть экземпляр модели, можно заполнить его массивом атрибутов с помощью метода fill:

Защитные атрибуты

В то время как параметр $fillable служит «белым списком» атрибутов, для которых разрешено массовое назначение. А параметр $guarded служит «чёрным списком». Параметр $guarded должен содержать массив атрибутов, для которых будет запрещено массовое назначение. Атрибутам, не вошедшим в этот массив, будет разрешено массовое назначение.

Чтобы разрешить массовое назначение всем атрибутам, свойство $guarded определяется как пустой массив:

Другие методы создания

firstOrCreate / firstOrNew

Есть ещё два метода, используемые для создания моделей с помощью массового заполнения: firstOrCreate и firstOrNew. Метод firstOrCreate пытается найти запись БД, используя указанные пары столбец/значение. Если модель не найдена в БД, запись будет вставлена в БД с указанными атрибутами.

updateOrCreate

Можно столкнуться с ситуациями, когда надо обновить существующую модель или создать новую, если её пока нет. Laravel предоставляет метод updateOrCreate для выполнения этой задачи за один шаг. Подобно методу firstOrCreate, метод updateOrCreate сохраняет модель, поэтому не надо вызывать метод save():

6: Запуск миграций и сидеров БД

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

Чтобы создать ключ шифрования для Laravel, используйте команду:

Создав ключ, вы сможете открыть приложение в браузере, указав имя хоста или IP-адрес и порт 8000:

На странице будет фраза:

Это значит, что приложение подключается к БД, но не находит таблицу по имени places. Давайте создадим таблицу places с помощью этой команды:

Вывод будет выглядеть так:

Обратите внимание: вместе с настроенной нами миграцией create_places_table было выполнено несколько других миграций. Они генерируются автоматически, если Laravel установлен

Сейчас мы не будем использовать эти дополнительные таблицы, но они пригодятся в будущем при расширении функционала приложения (например, при настройке аутентификации пользователей и планирования заданий). Пока что вы можете оставить эти таблицы без изменений.

На данный момент таблица places пуста. Запустите следующую команду, чтобы заполнить БД данными:

Эта команда запустит сидер, а он добавит в таблицу значения, которые мы определили в классе PlacesTableSeeder. Вывод будет выглядеть так:

Перезагрузите страницу в браузере. Вы увидите список городов.

Если вам нужно начать все сначала, вы можете очистить все таблицы вашей БД с помощью команды:
docker-compose exec app php artisan db:wipe

Чтобы запустить миграцию и заполнить таблицы данными с помощью одной команды, используйте эту команду:

Чтобы откатить миграцию, введите:

Это запустит метод down для всех классов миграции внутри каталога migrations. Как правило, этот метод удаляет все таблицы, созданные в классах миграции, оставляя те таблицы, которые могли быть созданы вручную. Вы увидите такой вывод:

Функция отката особенно полезна, если вы вносите изменения в модели и не можете использовать команду db:wipe (например, если одна БД используется несколькими системами).

Структура Репозитория

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

Например, у вас есть интерфейс UserRepository:

DelphiWebScript/DWS

interface UserRepository {}

1 interfaceUserRepository{}

И реализация EloquentUserRepository:

DelphiWebScript/DWS

class EloquentUserRepository implements UserRepository {}

1 classEloquentUserRepositoryimplementsUserRepository{}

Конкретная реализация будет связываться с главным интерфейсом через IoC контейнер Laravel, используя сервис-провайдер:

DelphiWebScript/DWS

/**
* Register
*/
public function register()
{
$this->app->bind(‘Cribbb\Repositories\User\UserRepository’, function($app)
{
return new EloquentUserRepository( new User );
});
}

1
2
3
4
5
6
7
8
9
10

/**

*Register

*/

publicfunctionregister()

{

      $this->app->bind(‘Cribbb\Repositories\User\UserRepository’, function($app)
      {
        return new EloquentUserRepository( new User );

      });

}

В мы потом сможем связать модель с классом, сделав её свойством класса:

DelphiWebScript/DWS

class EloquentUserRepository implements UserRepository {

/**
* @var Model
*/
protected $model;

/**
* Constructor
*/
public function __construct(User $model)
{
$this->model = $model;
}

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

classEloquentUserRepositoryimplementsUserRepository{

      /**
       * @var Model
       */
      protected $model;

      /**
       * Constructor
       */
      public function __construct(User $model)
      {
        $this->model = $model;
      }

}

Теперь, когда у нас есть экземпляр модели в классе, мы сможем выполнять запросы через модель и возвращать данные:

DelphiWebScript/DWS

/**
* Return all users
*
* @return Illuminate\Database\Eloquent\Collection
*/
public function all()
{
return $this->model->all();
}

1
2
3
4
5
6
7
8
9

/**

*Returnallusers

*

*@returnIlluminate\Database\Eloquent\Collection

*/

publicfunctionall()

{

      return $this->model->all();
    }

Надеюсь, это всё вам уже знакомо.

Create Model

To create model, run this artisan command.

It will create files with name Product.php & Blog.php at location /app/Models.

Open Product.php and write this code.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use HasFactory;

    public $timestamps = false;
}

Open Blog.php and write this code into it.

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Blog extends Model
{
    use HasFactory;
  
    public $timestamps = false;
}

События

Модели Eloquent инициируют несколько событий, что позволяет добавить к ним обработчики с помощью следующих методов: creating, created, updating, updated, saving, saved, deleting, deleted, restoring, restored. События позволяют выполнять код при каждом сохранении или изменении класса конкретной модели в БД.

Когда новая модель сохраняется первый раз, возникают события creating и created. Если модель уже существовала на момент вызова метода save(), вызываются события updating / updated. В обоих случаях также возникнут события saving / saved.

Вначале нужно определить свойство $events в Eloquent-модели, которая сопоставляет различные моменты жизненного цикла модели Eloquent с классами событий:

Наблюдатели

Если прослушивается много событий для определённой модели, можно использовать наблюдателей (обсерверов) для объединения всех слушателей в единый класс. В классах наблюдателей названия методов отражают те события Eloquent, которые нужно прослушивать. Каждый такой метод получает модель в качестве единственного аргумента. В Laravel нет стандартного каталога для наблюдателей, поэтому можно создать любой каталог для хранения классов наблюдателей:

Для регистрации наблюдателя используйте метод observe на наблюдаемой модели. Можно зарегистрировать наблюдателей в методе boot одного из сервис-провайдеров. В этом примере зарегистрируется наблюдатель в AppServiceProvider:

Внешние ссылки [ править ]

Викискладе есть медиафайлы по теме Laravel .

Официальный веб-сайт

vтеPHP
Люди
  • Энди Гутманс
  • Расмус Лердорф
  • Зеев Сураски
Ресурсы
  • Ускоритель ( Список )
  • Композитор
  • Редакторы
  • Библиотеки
  • ГРУША
Реализации
  • HHVM
  • HPHPc
  • Попугай
  • Персиковый пирог
  • Фалангер
  • Quercus
  • Zend Engine
Веб-фреймворки
  • CakePHP
  • CodeIgniter
  • Drupal
  • eZ Publish
  • Обезжиренный
  • ТопливоPHP
  • Орда
  • Joomla!
  • Ламины
  • Laravel
  • Li3 (ранее литий)
  • Люмен
  • Мидгард
  • MODx
  • Нетте Фреймворк
  • Phalcon
  • Поп PHP
  • PHP-Fusion
  • ПРАДО
  • Qcodo
  • Силекс
  • SilverStripe
  • Symfony
  • TYPO3
  • WordPress
  • XOOPS
  • Yii
  • Компоненты Zeta
Тестирование
  • Бехат
  • PHPUnit
ORM
  • Доктрина
  • Продвигать
Иды
  • Аптана
  • Codelobster
  • Затмение PDT
  • NetBeans
  • PHPEdit
  • PhpStorm
  • RadPHP
  • Zend Studio
Набор инструментов для виджетов
  • PHP-GTK
  • wxPHP
  • Категория
  • Commons
vтеВеб-фреймворки
.СЕТЬ
  • ASP.NET
    • Основной
    • AJAX
    • Динамические данные
    • MVC
    • Бритва
    • Веб-формы
  • Blazor
  • DNN
  • BFC
  • MonoRail
  • OpenRasta
  • Умбрако
  • WebSharper
C ++
  • CppCMS
  • Дрогон
  • Фисташ
  • Вес
Холодный синтез
  • CFWheels
  • Платформа ColdBox
  • Холодная весна
  • Блок предохранителей
  • Модель-клей
Common Lisp
  • Пещерный человек2
  • CL-HTTP
  • Веблоки
Haskell
  • Йесод
  • Щелчок
Ява
  • AppFuse
  • Гибкий
  • Грааль
  • GWT
  • ICEfaces
  • ItsNat
  • JavaServer Faces
  • JHipster
  • Jspx
  • JWt
  • OpenXava
  • Играть
  • Платформа удаленных приложений
  • RIFE
  • Шов
  • Слинг
  • Весна
  • Полосы
  • Стойки
  • Гобелен
  • Ваадин
  • Vert.x
  • Калитка
  • WaveMaker
  • ZK
JavaScript
  • Угловой / AngularJS
  • Backbone.js
  • Chaplin.js
  • Закрытие
  • Набор инструментов Dojo
  • Ember.js
  • Express.js
  • Внешний JS
  • jQuery
  • Knockout.js
  • Метеор
  • MooTools
  • Node.js
  • OpenUI5
  • Опытный образец
  • Реагировать
  • script.aculo.us
  • Sencha Touch
  • SproutCore
  • Svelte
  • Vue.js
  • Ваканда
Perl
  • Катализатор
  • Танцор
  • Мейсон
  • Maypole
  • Mojolicious
  • WebGUI
PHP
  • CakePHP
  • CodeIgniter
  • Drupal
  • Обезжиренный
  • ТопливоPHP
  • Поток
  • Grav
  • Гироскоп
  • Орда
  • Joomla
  • Кохана
  • Ламины
  • Laravel
  • Литий
  • Мидгард
  • MODX
  • Нетте
  • Phalcon
  • PHP-Fusion
  • Поп PHP
  • ПРАДО
  • ProcessWire
  • Qcodo
  • Силекс
  • SilverStripe
  • Symfony
  • TYPO3
  • WordPress
  • XOOPS
  • Yii
Python
  • BlueBream
  • Бутылка
  • CherryPy
  • CubicWeb
  • Джанго
  • FastAPI
  • Колба
  • Grok
  • Nevow
  • Pyjs
  • Пилоны
  • Пирамида
  • Дон Кихот
  • ТАКТИКА
  • Торнадо
  • TurboGears
  • web2py
  • Веб-ПО
  • Zope 2
  • подробнее
Рубин
  • Поход
  • Мерб
  • Падрино
  • Рубин на рельсах
  • Sinatra
Ржавчина
Scala
  • Поднимать
  • Играть
  • Скалатра
Болтовня
  • AIDA / Интернет
  • Приморский
Другие языки
  • Vibe.d ( D )
  • Application Express ( PL / SQL )
  • Grails ( Groovy )
  • Кеплер ( Lua )
  • OpenACS ( Tcl )
  • Феникс ( Эликсир )
  • SproutCore ( JavaScript — Ruby )
  • Фрамбезия ( Эрланг )

1: Подготовка тестового приложения

Давайте для начала загрузим тестовое приложение Laravel из этого GitHub репозитория. Вам понадобится ветка tutorial-02, которая включает установку Docker Compose, благодаря чему вы сможете запустить приложение в контейнерах. Мы будем использовать для работы свой домашний каталог, но вы можете выбрать любой другой.

Мы загрузили код приложения в формате .zip. Теперь его нужно распаковать с помощью команды unzip. Если вы еще не обновили индекс пакетов, сделайте это сейчас:

Установите пакет unzip:

Распакуйте архив:

Переименуйте полученный каталог в travellist-demo, чтобы его было проще найти:

Теперь у вас есть тестовое приложение. Можно приступать к настройке.

задача

В разделе задач будут перечислены все задачи, которые были запущены и выполняются. Он похож на Horizon, но Horizon поддерживает только драйвер Redis, и это не только пользовательский интерфейс, он также может взаимодействовать с очередью, в зависимости от того, как работает ваша очередь. Telescope — это просто пользовательский интерфейс, пользовательский интерфейс, который может работать с любым драйвером очереди.

На странице списка задач вы увидите название задачи, очередь и соединение, в котором она запущена, ее рабочий статус и опыт.

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

Задача автоматически пометит используемую модель Eloquent (каштан:), если модель пользователя использовалась, модель пользователя будет помечена и т. д.

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

Однако, если вы запускаете закрытую функцию, то информация, которую вы видите, не , заменяется  .

Рейтинг
( Пока оценок нет )
Editor
Editor/ автор статьи

Давно интересуюсь темой. Мне нравится писать о том, в чём разбираюсь.

Понравилась статья? Поделиться с друзьями:
Люкс-хост
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: