Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel Model Events - I'm a bit confused about where they're meant to go

So the way I see it is that a good Laravel application should be very model- and event-driven.

I have a Model called Article. I wish to send email alerts when the following events happen:

  • When an Article is created
  • When an Article is updated
  • When an Article is deleted

The docs say I can use Model Events and register them within the boot() function of App\Providers\EventServiceProvider.

But this is confusing me because...

  • What happens when I add further models like Comment or Author that need full sets of all their own Model Events? Will the single boot() function of EventServiceProvider just be absolutely huge?
  • What is the purpose of Laravel's 'other' Events? Why would I ever need to use them if realistically my events will only respond to Model CRUD actions?

I am a beginner at Laravel, having come from CodeIgniter, so trying to wrap my head around the proper Laravel way of doing things. Thanks for your advice!

like image 632
Jack Avatar asked May 19 '15 17:05

Jack


People also ask

Are laravel events asynchronous?

Laravel supports asynchronous events by allowing Listeners (which are classes) to implement a ShouldQueue marker interface to indicate that if a queue system is available the Listener should not execute immediately but a queue entry should be made that will, in turn, execute the Listener "later".

How do events work in laravel?

Laravel's events provide a simple observer pattern implementation, allowing you to subscribe and listen for various events that occur within your application. Event classes are typically stored in the app/Events directory, while their listeners are stored in app/Listeners .

Is laravel event driven?

Laravel events provide a simple observer implementation, allowing you to subscribe and listen for various events that occur in your application. Some of these events are fired automatically by the framework (Laravel) when certain activities occur.


Video Answer


2 Answers

In your case, you may also use following approach:

// Put this code in your Article Model  public static function boot() {      parent::boot();      static::created(function($article) {         Event::fire('article.created', $article);     });      static::updated(function($article) {         Event::fire('article.updated', $article);     });      static::deleted(function($article) {         Event::fire('article.deleted', $article);     }); } 

Also, you need to register listeners in App\Providers\EventServiceProvider:

protected $listen = [     'article.created' => [         'App\Handlers\Events\ArticleEvents@articleCreated',     ],     'article.updated' => [         'App\Handlers\Events\ArticleEvents@articleUpdated',     ],     'article.deleted' => [         'App\Handlers\Events\ArticleEvents@articleDeleted',     ], ]; 

Also make sure you have created the handlers in App\Handlers\Events folder/directory to handle that event. For example, article.created handler could be like this:

<?php namespace App\Handlers\Events;  use App\Article; use App\Services\Email\Mailer; // This one I use to email as a service class  class ArticleEvents {      protected $mailer = null;      public function __construct(Mailer $mailer)     {         $this->mailer = $mailer;     }      public function articleCreated(Article $article)     {         // Implement mailer or use laravel mailer directly         $this->mailer->notifyArticleCreated($article);     }      // Other Handlers/Methods... } 
like image 173
The Alpha Avatar answered Sep 19 '22 18:09

The Alpha


Recently I came to same problem in one of my Laravel 5 project, where I had to log all Model Events. I decided to use Traits. I created ModelEventLogger Trait and simply used in all Model class which needed to be logged. I am going to change it as per your need Which is given below.

<?php  namespace App\Traits;  use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Event;  /**  * Class ModelEventThrower   * @package App\Traits  *  *  Automatically throw Add, Update, Delete events of Model.  */ trait ModelEventThrower {      /**      * Automatically boot with Model, and register Events handler.      */     protected static function bootModelEventThrower()     {         foreach (static::getModelEvents() as $eventName) {             static::$eventName(function (Model $model) use ($eventName) {                 try {                     $reflect = new \ReflectionClass($model);                     Event::fire(strtolower($reflect->getShortName()).'.'.$eventName, $model);                 } catch (\Exception $e) {                     return true;                 }             });         }     }      /**      * Set the default events to be recorded if the $recordEvents      * property does not exist on the model.      *      * @return array      */     protected static function getModelEvents()     {         if (isset(static::$recordEvents)) {             return static::$recordEvents;         }          return [             'created',             'updated',             'deleted',         ];     } }  

Now you can use this trait in any Model you want to throw events for. In your case in Article Model.

<?php namespace App;  use App\Traits\ModelEventThrower; use Illuminate\Database\Eloquent\Model;  class Article extends Model {      use ModelEventThrower;      //Just in case you want specific events to be fired for Article model     //uncomment following line of code     // protected static $recordEvents = ['created'];  } 

Now in your app/Providers/EventServiceProvider.php, in boot() method register Event Handler for Article.

 public function boot(DispatcherContract $events)  {      parent::boot($events);      $events->subscribe('App\Handlers\Events\ArticleEventHandler');  } 

Now create Class ArticleEventHandler under app/Handlers/Events directory as below,

<?php namespace App\Handlers\Events;  use App\Article;  class ArticleEventHandler{      /**      * Create the event handler.      *      * @return \App\Handlers\Events\ArticleEventHandler      */     public function __construct()     {         //     }      /**     * Handle article.created event     */     public function created(Article $article)    {       //Implement logic    }     /**    * Handle article.updated event    */     public function updated(Article $article)    {       //Implement logic    }    /**   * Handle article.deleted event   */    public function deleted(Article $article)   {      //Implement logic   }   /**  * @param $events  */  public function subscribe($events)  {      $events->listen('article.created',             'App\Handlers\Events\ArticleEventHandler@created');      $events->listen('article.updated',             'App\Handlers\Events\ArticleEventHandler@updated');      $events->listen('article.deleted',             'App\Handlers\Events\ArticleEventHandler@deleted');  }  } 

As you can see from different answers, from different Users, there are more than 1 way of handling Model Events. There are also Custom events That can be created in Events folder and can be handled in Handler folder and can be dispatched from different places. I hope it helps.

like image 40
pinkal vansia Avatar answered Sep 18 '22 18:09

pinkal vansia