Создание событий (Event) в Laravel 5

Ромчик
8

laravelДоброго времени суток. В данной статье мы поговорим о событиях (events) в Laravel 5. И применим на практике использование события. Events в Laravel – это простая реализация паттерна Obserever. О паттерне Observer можно прочитать тут.

Мы можем подписаться на событие (event), которое будет сгенерировано в некотором месте нашего приложения и обработано как правило в этом же запросе. Давайте приступим.

И так, ситуация следующая.

Постановка задачи

У нас есть таблица users:

01

Ей соответствует модель User.php

<?php
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;
   /**
   * The database tableused by the model.
   *
   * @var string
   */
   protected $table ='users';
    
   /**
   * The attributes that are mass assignable.
   *
   * @var array
   */

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

   /**
   * The attributes excluded from the model's JSON form.
   *
   * @var array
   */

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

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

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

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

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». Более подробно прочитать по redirect в Laravel.

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

 
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.

Создание event и listener в Laravel 5

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

02

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

Я не буду описывать как создать файл миграции и затем запустить эту миграцию. Это тема для отдельной статьи.

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

app/Providers/EventServiceProvider.php

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

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

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

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

php artisan event:generate

У нас появились два файла:

App\Events\AddLogs.php

и

App\Handlers\Events\Log

Вот листинг первого:

<?php
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 передаст дальше слушателю.

<?php
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 [];
    }
}

Теперь рассмотрим файл слушателя:

<?php
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)
    {

    }
}

Изменим его:

<?php
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 готов к использованию.

Вызов Event в приложении Laravel 5

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

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

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

И метод разблокировки:

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

Проверяем и вуаля: мы пишем логи при помощи события и слушателя.

Вывод.

Как видите все очень просто. Создается event (событие), которому соответствуют один или несколько listener (слушателей). Затем в приложении мы вызываем событие, при вызове события управление передается его слушателям, в которых и реализованы правила обработки данного события.

Понравилась статья? Поделись с друзьями.
  • Add to favorites
  • Добавить ВКонтакте заметку об этой странице
  • Twitter
  • Facebook
  • Мой Мир
  • LiveJournal
  • Одноклассники
  • Блог Я.ру
  • MySpace
  • FriendFeed
  • В закладки Google
  • Google Buzz
  • Яндекс.Закладки
  • Reddit
  • StumbleUpon
  • Technorati
  • del.icio.us
  • БобрДобр
  • LinkedIn
  • Memori.ru
  • Сто закладок
  • Blogger

  • Евгений - 27.01.2016 в 07:36

    А для чего ещё могут использоваться события? Кроме логирования. И возможно ли поставить событие на все методы контроллера, к примеру, после добавления новой строки в бд чтобы вызывалось событие?

  • Александр - 16.10.2016 в 21:26

    А в чем вообще смысл этих событий? Почему в методах лок и анлок просто не выполнять sql запрос в базу или не вызывать какой-либо метод с прописанной в нем необходимой догикой?

    • Anton - 20.11.2016 в 03:18

      Лучше ли это использовать вместо обычного запроса в базу данных, путем создания соответствующего экземпляра модели Log, например, где будет заноситься лог в базу?

  • Алексеей - 24.04.2017 в 15:20

    Откуда в слушателе берётся класс Adminlog?

    • Ромчик - 24.04.2017 в 15:33

      Adminlog — это модель, а в таблице adminlog хранятся логи. Adminlog::create — мы создаем запись в нашей таблице с логами.

  • ivan - 14.03.2018 в 22:53

    Мрак, так ничего и не заработало.

    • Ромчик - 15.03.2018 в 08:23

      Странно. По-моему в Laravel мрака нет, все просто. А ошибка какая?

  • ©2012-2018 По всем вопросам обращайтесь через форму обратной связи

    Яндекс.Метрика