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

2021-12-26 00:00:00 php laravel eloquent

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

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.

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

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

在 appProvidersEventServiceProvider.php 中

In appProvidersEventServiceProvider.php

<?php namespace AppProviders;

...

class EventServiceProvider extends ServiceProvider {

    ...

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

        Issue::saving('AppHandlersEventsSetIssueStatus');
    }

}

在 appHandlersEventsSetIssueStatus.php 中

In appHandlersEventsSetIssueStatus.php

<?php namespace AppHandlersEvents;

...

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

}

感谢您的宝贵时间.

推荐答案

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

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.

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

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 IlluminateDatabaseEloquentModel;
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)

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

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:

<?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 IlluminateDatabaseEloquentModel;
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.

相关文章