Laravel:使用Query Builder或Eloquent ORM时,在每次插入/更新时执行一些任务


Laravel: performing some task on every insert/update when using Query Builder or Eloquent ORM

问题

无论我使用的是Eloquent还是Query Builder,我都希望在Laravel 4中的数据库表的每次插入/更新中自动添加created_bymodified_by字段。但是,并不是我的所有表都有这些字段,所以任何解决方案都必须在添加之前检查这些列是否存在。

尝试的解决方案

我扩展了Illuminate'Database'Eloquent'Model类,并编写了一个重写方法save(),以便为保存的每个记录添加一些额外的元数据字段。

这很好,只是如果我使用查询生成器执行插入,则会绕过它。查看Model类,数据库操作实际上是使用查询生成器完成的。

我已经看过Illuminate'Database'Query'Builder模型,看起来我可能会为insert()update()编写重写方法。

这是为每次插入/更新执行一些任务的明智方法吗?还是我以后会遇到麻烦?

添加到以上答案中。你可以做这样的事。

在应用程序/模型中创建一个名为BaseModel.php的类,扩展''Eloquent

class BaseModel extends 'Eloquent{
public static function boot()
{
    parent::boot();
    static::creating(function($model)
    {
        //change to Auth::user() if you are using the default auth provider
        $user = Confide::user();
        $model->created_by = $user->id;
        $model->updated_by = $user->id;
    });
    static::updating(function($model)
    {
        //change to Auth::user() if you are using the default auth provider
        $user = Confide::user();
        $model->updated_by = $user->id;
    });
  }
}

然后,在您的单个模型类中,您需要扩展BaseModel,而不是''Eloquent

class Product extends BaseModel {
    protected $table = 'product';
    //Booting the base model to add created_by and updated_by to all tables
    public static function boot()
    {
        parent::boot();
    }
}

现在,每当保存或更新模型时,created_by和updated_by字段都会自动更新。

注意:只有通过Eloquent进行保存或更新时,这才有效。对于查询生成器,您可以有一个通用的方法来获取和附加created_by和update_by列更新。

您决不能重写save方法来重写和添加您的函数。

您必须使用雄辩提供的模型事件功能来实现这一点。

简单地说,您必须为模型定义一个保存事件,以覆盖/设置/检查模型要保存的数据。

用户模型类中的一个简单示例:

//Executed when loading model
public static function boot()
{
     parent::boot();
     User::creating(function($user){
         $user->value1 = $user->value2 +1;
     });
}

更多信息:http://four.laravel.com/docs/eloquent#model-事件

在Laravel中,如果您想从单个点在每次保存/更新时调用单个方法,而不在每个扩展模型中进行任何额外的更改,则可以为雄辩的事件提供自定义侦听器。正如文档所说,它只能针对每个模型进行。但是创建自定义侦听器允许访问任何模型中的任何事件。

只需在EventServiceProvider中的boot()方法中添加一个监听器,如下所示,并进行相应的修改。

Event::listen(['eloquent.saving: *', 'eloquent.creating: *'], function($event){
        //your method content
        //returning false will cancel saving the model
 });

请注意,通配符用于匹配任何模型。有关事件的更多信息,请参阅文档。

如果您想使用Query Builder,并且Eloquent是在不扩展核心组件(我认为没有必要)的情况下解决这一问题的唯一方法,您可以使用事件系统

链接:http://laravel.com/docs/events

因此,您可以使用user.custom.save之类的事件,然后创建一个与查询生成器一起使用的函数,查询生成器在最后会触发此事件,与Eloquent相同。

示例:

class User extends Eloquent
{
    public function save()
    {
        Event::fire('user.custom.save', array($this));
        parent::save();
    }
}

您可以使用venturecraft可修订包,因为在这个包的表中,您需要的所有信息都已经存储,您只需要这个包就可以以优雅的方式获取它们:https://github.com/fico7489/laravel-revisionable-upgrade