Laravel模型事件 - 我对它们的目的地有点困惑

Jac*_*ack 55 php laravel laravel-5

所以我看待它的方式是一个好的Laravel应用程序应该是非常模型和事件驱动的.

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

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

文档说我可以使用模型事件并在boot()函数中注册它们App\Providers\EventServiceProvider.

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

  • 当我添加更多类似CommentAuthor需要完整的所有模型事件的模型时会发生什么?单一boot()功能EventServiceProvider是否绝对巨大?
  • Laravel的"其他"活动的目的是什么?为什么我真的需要使用它们,如果我的事件只会响应模型CRUD操作?

我是Laravel的初学者,来自CodeIgniter,因此试图绕着正确的Laravel做事方式.谢谢你的建议!

The*_*pha 39

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

// 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);
    });
}
Run Code Online (Sandbox Code Playgroud)

此外,您需要在以下位置注册侦听器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',
    ],
];
Run Code Online (Sandbox Code Playgroud)

还要确保已在App\Handlers\Eventsfolder /目录中创建处理程序以处理该事件.例如,article.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...
}
Run Code Online (Sandbox Code Playgroud)


pin*_*sia 25

最近我在我的一个Laravel 5项目中遇到了同样的问题,我必须记录所有模型事件.我决定用Traits.我创建了ModelEventLoggerTrait,只是在需要记录的所有Model类中使用.我将根据您的需要对其进行更改,具体如下.

<?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',
        ];
    }
} 
Run Code Online (Sandbox Code Playgroud)

现在,您可以在要为其投掷事件的任何模型中使用此特征.在你的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'];

}
Run Code Online (Sandbox Code Playgroud)

现在在你app/Providers/EventServiceProvider.phpboot()方法寄存器Event Handler中Article.

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

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

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

}
Run Code Online (Sandbox Code Playgroud)

从不同的用户可以看出,从不同的答案中可以看出,处理模型事件的方法不止一种.还有自定义事件可以在事件文件夹中创建,可以在Handler文件夹中处理,可以从不同的地方分派.我希望它有所帮助.


Bor*_*nte 9

我发现这是做你想做的最干净的方法.

1.-为模型创建观察者(ArticleObserver)

use App\Article;

class ArticleObserver{

  public function __construct(Article $articles){
    $this->articles = $articles
  }

  public function created(Article $article){
    // Do anything you want to do, $article is the newly created article
  }

}
Run Code Online (Sandbox Code Playgroud)

2.-创建一个新的ServiceProvider(ObserversServiceProvider),记得将它添加到config/app.php

use App\Observers\ArticleObserver;
use App\Article;
use Illuminate\Support\ServiceProvider;

class ObserversServiceProvider extends ServiceProvider
{

  public function boot()
  {
    Article::observe($this->app->make(ArticleObserver::class));
  }

  public function register()
  {
    $this->app->bindShared(ArticleObserver::class, function()
        {
            return new ArticleObserver(new Article());
        });
  }

}
Run Code Online (Sandbox Code Playgroud)