在 Laravel 5 中使用模型事件监听器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29818317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 11:25:36  来源:igfitidea点击:

Using Model Events Listener in Laravel 5

phplaraveleloquent

提问by zss61890

I would like to make sure that I correctly used model events listeners in Laravel 5 and I didn't messed up nothing (listener vs handler?). My solution works fine, but I wonder if I developed according to concept and convention of Laravel 5.

我想确保我在 Laravel 5 中正确使用了模型事件侦听器,并且我没有搞砸任何事情(侦听器与处理程序?)。我的解决方案工作正常,但我想知道我是否根据 Laravel 5 的概念和约定开发。

Goal:Always set $issue->status_id on some value when model is saving.

目标:在模型保存时始终将 $issue->status_id 设置为某个值。

In app\Providers\EventServiceProvider.php

在 app\Providers\EventServiceProvider.php

<?php namespace App\Providers;

...

class EventServiceProvider extends ServiceProvider {

    ...

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

        Issue::saving('App\Handlers\Events\SetIssueStatus');
    }

}

In app\Handlers\Events\SetIssueStatus.php

在 app\Handlers\Events\SetIssueStatus.php

<?php namespace App\Handlers\Events;

...

class SetIssueStatus {

    ...

    public function handle(Issue $issue)
    {
        if (something)
        {   
            $issueStatus = IssueStatus::where(somethingElse)->firstOrFail();
        }
        else 
        {
            $issueStatus = IssueStatus::where(somethingAnother)->firstOrFail();
        }

        // issue_status() is One-to-One relations with IssueType (belongsTo)
        $issue->issue_status()->associate($issueStatus);
    }

}

Thank you for your time.

感谢您的时间。

回答by Fabio Antunes

As you said you have a working version and it's a valid one, now that's up to you to figure out if it's ok for you.

正如您所说,您有一个工作版本并且它是有效的,现在由您来确定它是否适合您。

Just to clarify I'm not saying that these are better solutions, they are just a valid different way.

澄清一下,我并不是说这些是更好的解决方案,它们只是一种有效的不同方式。

Since what you are doing is specific to the Issue model or at least it doesn't seem to be a generic event, you could set it up on your model directly

由于您正在做的事情特定于问题模型,或者至少它似乎不是一个通用事件,您可以直接在您的模型上进行设置

<?php namespace App;

use Illuminate\Database\Eloquent\Model;
use IssueStatus;

class Issue extends Model {


    protected static function boot()
    {
        parent::boot();

        static::saving(function($issue){
            if (something)
            {   
                $issueStatus = IssueStatus::where(somethingElse)->firstOrFail();
            }
            else 
            {
                $issueStatus = IssueStatus::where(somethingAnother)->firstOrFail();
            }

            // issue_status() is One-to-One relations with IssueType (belongsTo)
            $issue->issue_status()->associate($issueStatus);

        });
    }
}

but if your event is indeed a generic one and you want to use it across multiple Models, you could achieve the same thing. You just need to extract the code from the model and use traits (like you do with soft deletes)

但如果您的事件确实是一个通用事件,并且您想在多个模型中使用它,则可以实现相同的目的。您只需要从模型中提取代码并使用特征(就像使用软删除一样)

First we create our trait(in this case we created on the root of our App) and extract the code, I wrote before, from the model:

首先,我们创建我们的 trait(在本例中,我们在 App 的根目录上创建)并从模型中提取我之前编写的代码:

<?php namespace App

use IssueStatus;

trait IssueStatusSetter
{
    protected static function boot()
    {
        parent::boot();

        static::saving(function($model){
            if (something)
            {   
                $issueStatus = IssueStatus::where(somethingElse)->firstOrFail();
            }
            else 
            {
                $issueStatus = IssueStatus::where(somethingAnother)->firstOrFail();
            }

            // issue_status() is One-to-One relations with IssueType (belongsTo)
            $model->issue_status()->associate($issueStatus);

        });
    }
}

Now on the models where you want to use it, you just import the trait and declare it's use:

现在在你想要使用它的模型上,你只需导入特征并声明它的使用:

<?php namespace App;

use Illuminate\Database\Eloquent\Model;
use IssueStatusSetter;

class Issue extends Model {

    use IssueStatusSetter;

}

Now this last option I showed you it's a generic option you have that you could apply to every Model by just declaring it's use on the top of your model.

现在我向您展示的最后一个选项是一个通用选项,您可以通过声明它在模型顶部使用来应用于每个模型。