Laravel模型事件 - 我对它们应该去哪里有点困惑

2022-08-30 09:20:51

因此,我认为一个好的Laravel应用程序应该非常模型和事件驱动。

我有一个名为 .我希望在发生以下事件时发送电子邮件警报:Article

  • 创建文章时
  • 当文章更新时
  • 删除文章时

文档说我可以使用模型事件并在 的功能中注册它们。boot()App\Providers\EventServiceProvider

但这让我感到困惑,因为...

  • 当我添加更多模型(如或需要所有模型事件的完整集合)时,会发生什么情况?单一功能会是绝对巨大的吗?CommentAuthorboot()EventServiceProvider
  • 拉拉维尔的“其他”活动的目的是什么?如果实际上我的事件仅响应模型 CRUD 操作,为什么还需要使用它们?

我是Laravel的初学者,来自CodeIgniter,所以试图把我的头缠绕在Laravel正确的做事方式上。感谢您的建议!


答案 1

在您的情况下,您也可以使用以下方法:

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

另外,您需要在以下位置注册监听器: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',
    ],
];

还要确保已在文件夹/目录中创建了处理程序来处理该事件。例如,处理程序可能如下所示:App\Handlers\Eventsarticle.created

<?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...
}

答案 2

最近,我在 Laravel 5 的一个项目中遇到了同样的问题,我必须记录所有模型事件。我决定使用.我创建了Trait,并简单地用于所有需要记录的模型类。我将根据您的需要更改它,如下所示。TraitsModelEventLogger

<?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',
        ];
    }
} 

现在,您可以在要为其引发事件的任何模型中使用此特征。在模型中,Article

<?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'];

}

现在,在 方法中注册 的事件处理程序。app/Providers/EventServiceProvider.phpboot()Article

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

现在在目录下创建类,如下所示,ArticleEventHandlerapp/Handlers/Events

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

}

从不同的答案中,从不同的用户那里可以看出,处理模型事件的方法不止一种。还有自定义事件,可以在事件文件夹中创建,可以在Handler文件夹中处理,并且可以从不同位置调度。我希望它有帮助。


推荐