Публикации - Laravel

Решение типовых задач на Laravel - События

Events в Laravel позволяют подписываться на события, которые генерируются на стороне сервера.

3 действия:

1 Создать само событие.

2. Создать обработчик события или подписаться на созданное событие.

3. Вызывать событие.

Классы событий находятся в папке app/Events. Классы обработчиков (или прослушивателей) событий – в папке app/Listeners. А вызывать событие можно в любом месте вашего проекта.

Создание события

Команда artisan: создать класс события. Листинг 26.1

 php artisan make:event PodcastWasPurchased

Подписка на события

Сервис-провайдер EventServiceProvider - это удобное место для регистрации классов слушателей событий. В массиве listen перечисляются названия события (в ключе массива) и название класса, который его обрабатывает. Например, для нашего PodcastWasPurchased:

Подписка на события. Листинг 26.2

protected $listen = [
    'App\Events\PodcastWasPurchased' => [
        'App\Handlers\Events\EmailPurchaseConfirmation@handle',
    ],
];

Для генерации исполнителя (handler) события используйте artisan-команду handler:event:

 Команда handler:event. Листинг 26.3

php artisan handler:event EmailPurchaseConfirmation --event=PodcastWasPurchased

Вызов события

Запускать события можно так:

 Запуск события. Листинг 26.4

use Event; 
use App\Events\TimeEvent; 
Event::fire(new TimeEvent());

Вместо фасада Event можно использовать хелпер:

 Использование хелпера event для запуска события. Листинг 26.5

event(new PodcastWasPurchased($podcast));

 

Слушатели в функциях замыканиях

Чтобы упростить себе работу и не создавать два класса, вы можете создать слушателя в виде функции-замыкания. Сделать это можно в методе boot сервис-провайдера EventServiceProvider:

 Прослушиватель событий в функции замыкании. Листинг 26.6

Event::listen('App\Events\PodcastWasPurchased', function($event)
{
    // Обработка события...
});

Event:generate

Использование двух команд -  make:event и handler:event - каждый раз, когда вам нужно создать обработчик события - это неудобно. Вместо этого, можно заполнить массив listen в EventServiceProvider:

 Массив listen. Листинг 26.7

protected $listen = [
        'App\Events\UserLogin' => [
        'App\Listeners\UserLoginListener',
        ],
];

И выполнить artisan-команду event:generate. Эта команда анализирует listen и создает все необходимые классы событий и обработчиков событий:

Event:generate. Листинг 26.8

php artisan event:generate

События моделей

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

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

Регистрировать слушателей событий модели можно в вашем сервис-провайдере EventServiceProvider. Например,

 Регистрация событий. Листинг 26.9

 public function boot(DispatcherContract $events)
{
    parent::boot($events);

 
    User::creating(function($user)
{
dd($user);
    });
}

Подписчики

Подписчики на события (Event Subscribers) - классы, которые могут быть подписаны на несколько событий и содержать сразу несколько обработчиков событий. Такой класс должен иметь метод subscribe, который принимает в аргументах инстанс диспетчера событий:

 Класс подписчик событий. Листинг 26.10

 class UserEventHandler {

 
    /**
     * Событиеlogin.
     */
    public function onUserLogin($event)
    {
        //
    }

 
    /**
     * Событие logout.
     */
    public function onUserLogout($event)
{
        //
    }

 
    /**
     * Регистрация подписчиков в методе subscriber.
*
     * @param  Illuminate\Events\Dispatcher  $events
     * @return array
*/
    public function subscribe($events)
    {
        $events->listen('App\Events\UserLoggedIn', 
'UserEventHandler@onUserLogin');

 
        $events->listen('App\Events\UserLoggedOut', 
'UserEventHandler@onUserLogout');
}

 
}

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

Регистрация подписчика. Листинг 26.11

$subscriber = new UserEventHandler;

 
Event::subscribe($subscriber);

Пример использования событий

У нас имеется таблица users, которой соответсвует следующая модель

 Модель User. Листинг 26.12

 

			
namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;

 
class User extends Model implements AuthenticatableContract,AuthorizableContract,CanResetPasswordContract
{
   use Authenticatable, Authorizable, CanResetPassword;

 
   protected $table ='users';

 

 
   protected $fillable = ['username', 'password', 'blocked'];

 
  
   protected $hidden = ['password', 'remember_token'];
}

Наша задача: когда из админки блокируем пользователя, полю blocked присваиваем значение 1 или, наоборот, при разблокировке blocked присваиваем 0. Мы должны записывать данные действие в лог. И это мы реализуем с помощью event.

Есть контроллер UserController, в котором есть два метода – один блокирует пользователя, второй разблокирует пользователя.

Метод блокировки пользователя:

 Метод lock. Листинг 26.13

public function lock($id)
{
    $user = User::find($id);
    if($user){
      $user->blocked = 1;         
      $user->save();
      return redirect()->back()->with('message','saved');
    }
   return redirect()->back()->with('errMessage','error');
}

Рассмотрим подробнее этот метод. В метод lock передается параметр $id, где $id – это ID пользователя, которого мы хотим заблокировать. Дальше мы ищем пользователя по его ID, необходимо для того, чтобы избежать блокировки несуществующего пользователя. Если пользователь найден, то атрибуту blocked присваиваем значение 1 и сохраняем. Дальше редиректим обратно с сообщением «saved».

И второй метод разблокировки пользователя:

Метод unlock. Листинг 26.14

 public function unlock($id)
{
    $user = User::find($id);
    if($user){
        $user->blocked = 0;         
        $user->save();
        return redirect()->back()->with('message','saved');
    }
    return redirect()->back()->with('errMessage','error');
}

Данный метод аналогичен предыдущему, кроме того, что мы атрибуту blocked присваиваем значение 0.

Теперь можно перейти к решению нашей задачи. Первое - создадим таблицу logs со следующей структурой:

id

user_id

data

created_at

Где user_id – ID пользователя, который осуществил блокировку (мы же в админке работаем только авторизованным пользователем), data – это поле в которое мы будем записывать «ID: $id Status: $blocked» $id – это ID блокируемого или разблокируемого пользователя, а $blocked – это статус: 1- заблокирован, 0 — не заблокирован.

Теперь перейдем к созданию event в Laravel 5. Для этого в начале откроем файл app/Providers/EventServiceProvider.php.

И в свойстве $listen добавим следующий код

Свойство $listen файла EventServiceProvider. Листинг 26.15

'App\Events\AddLogs' =>
   [          
     'App\Handlers\Events\Log@handle',
   ],

Мы добавили в массив ключ и значение, где ключем является событие (event) AddLogs, а элементом массив его слушателе (listener). В нашем случае массив состоит из одного слушателя Log.

Теперь запустим команду artisan для генерации файлов события (event) и слушателя (listener):

Генерация файлов события. Листинг 26.16

 php artisan event:generate

У нас появились два файла: App\Events\AddLogs.php и App\Handlers\Events\Log.php.

 Файл AddLogs.php. Листинг 26.17

 
namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

 
class AddLogs extends Event
{
    use SerializesModels;
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {

 
    }
    /**
     * Get the channels the event should be broadcast on.
     *
     * @return array
     */
    public function broadcastOn()
    {
        return [];
    }
}

Изменим его, с учетом того, что в наше событие надо передать два параметра $user_id и $data, которые event передаст дальше слушателю.

 Измененный файл события AddLogs.php. Листинг 26.18

 

			
namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

 
class AddLogs extends Event
{
    use SerializesModels;
    public $user_id;
    public $data;
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($user_id,$data)
    {
        $this->user_id = $user_id;
        $this->data = $data;
    }
    /**
     * Get the channels the event should be broadcast on.
     *
     * @return array
     */
    public function broadcastOn()
    {
        return [];
    }
}

Рассмотрим файл слушателя событий.

Слушатель событий, файл Log.php. Листинг 26.19

 

			
namespace App\Handlers\Events;
use App\Events\AddLogs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

 
class Log
{
    /**
     * Create the event handler.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * Handle the event.
     *
     * @param  AddLogs $event
     * @return void
     */
    public function handle(AddLogs $event)
    {

 
    }
}

Изменим файл слушателя.

 Измененный файл слушателя Log.php. Листинг 26.20

 

			
namespace App\Handlers\Events;
use App\Log;
use App\Events\AddLogs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

 
class Log
{
    /**
     * Create the event handler.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * Handle the event.
     *
     * @param  AddLogs $event
     * @return void
     */

 
    public function handle(AddLogs $event)
    {

         Adminlog::create([
            'user_id' => $event->user_id,
            'data' => $event->data,
        ]);
    }
}

Наш event готов к использованию.

Давайте вернемся к контроллеру UserController и поправим методы lock и unlock – запустим наше событие. Это можно сделать при помощи метода fire фасада Event.

Метод блокировки:

Метод lock. Листинг 26.21

 public function lock($id)
{
    $user = User::find($id);
    if($user){
        $user->blocked = 1;         
        $user->save();
        //вызываем event
            Event::fire(new AddLogs(Auth::user()->id,
'ID: '.$user->id.' Status: 1'));
        return redirect()->back()->with('message','saved');
    }
    return redirect()->back()->with('errMessage','error');
}

Метод разблокировки

Метод unlock. Листинг 26.22

 public function unlock($id)
{
    $user = User::find($id);
    if($user){
    $user->blocked = 0;         
    $user->save();
        //вызываем event
    Event::fire(new AddLogs(Auth::user()->id,'ID: '.$user->id.' Status: 0'));
    return redirect()->back()->with('message','saved');
    }
    return redirect()->back()->with('errMessage','error');
}

Количество комментариев: 0

Для того, чтобы оставить коментарий необходимо зарегистрироваться


Изображения Видео

1. Подключение CKEditor https://artisansweb.net/install-use-ckeditor-laravel/#comments
2. Регистрация и авторизация https://know-online.com/post/laravel-reg
3. Что нового в Laravel 8 https://sergeymukhin.com/blog/chto-novogo-v-laravel-80
4. Авторизация Sanctum <iframe width="560" height="315" src="https://www.youtube.com/embed/MT-GJQIY3EU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>