Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to catch model events in pivot tables

I want to track (record) the changes made to each database row. This means, saving a log of each action (insert, update, delete) made to each record of each table.

This issue is solved for models, as they extend from a BaseModel and I'm using model events. However, I cannot seem to find a way to record the changed from pivot tables.

Given the following tables users, profiles and profile_user(profile_id, user_id), I have the following code:

class User extends BaseModel {
    public function profiles() {
        return $this->belongsToMany('Profile');
    }
}

class Profile extends BaseModel {
    public function users() {
        return $this->belongsToMany('User');
    }
}

abstract class BaseModel extends Model {
    public static function boot() {
        parent::boot();

        static::created(function($model) {
            return LogTracker::saveRowCreatedOrUpdated($model, true);
        });

        static::updated(function($model) {
            return LogTracker::saveRowCreatedOrUpdated($model, false);
        });

        static::deleted(function($model) {
            return LogTracker::saveRowDeleted($model);
        });
    }
}

This allows me to record the changes from user and profile but not from profile_user.

I've tried to create a ProfileUser model that extends from Pivot (Illuminate\Database\Eloquent\Relations\Pivot) where I defined the model events but that didn't work.

I'm guessing that's because I never create a new instance of this model. So, I've added the following to my User model (and similar code to Profile):

class User extends BaseModel {
    // (...)
    public function newPivot(Eloquent $parent, array $attributes, $table, $exists) {
        if ($parent instanceof Profile) {
            return new ProfileUser($parent, $attributes, $table, $exists);
        }
        return parent::newPivot($parent, $attributes, $table, $exists);
    }
    // (...)
}

Still, the events are never fired (actually this method is never executed).

I am updating the relationship through sync():

$user->profiles()->sync(explode(',', $values["profiles"]));

I'm looking for a solution that doesn't involve firing a custom event (as this means that I would have to do this for each pivot table in database).

How can I use model events in pivot tables?

like image 785
Luís Cruz Avatar asked Oct 20 '22 21:10

Luís Cruz


1 Answers

I am aware you don't want a custom event situation but I cannot find any non-custom solution.

You can however do a very simple custom one (pretty much pulled right from Laravel docs):

DB::listen(function($sql, $bindings, $time)
{
    //regex matching for tables in SQL query
    //as well as firing your event handling code
});

http://laravel.com/docs/4.2/database#running-queries

like image 133
Alexander Kerchum Avatar answered Oct 24 '22 09:10

Alexander Kerchum