Laravel Relationship Events

Packages

July 9th, 2018

relationship-events.png

Laravel Relationship Events is a package by Viacheslav Ostrovskiy that adds extra model relationship events. This package comes with the following traits that are used to register listeners on a model’s boot() method:

  • HasOneEvents
  • HasBelongsToEvents
  • HasManyEvents
  • HasBelongsToManyEvents
  • HasMorphOneEvents
  • HasMorphToEvents
  • HasMorphManyEvents
  • HasMorphToManyEvents
  • HasMorphedByManyEvents

And from the above traits, here’s an example of a few events on a Country model that has many Users using the HasManyEvents trait:

1namespace App\Models;
2
3use App\User;
4use Chelout\RelationshipEvents\Concerns\HasManyEvents;
5use Illuminate\Database\Eloquent\Model;
6
7class Country extends Model
8{
9 use HasManyEvents;
10
11 protected $fillable = [
12 'name',
13 ];
14
15 public function users()
16 {
17 return $this->hasMany(User::class);
18 }
19
20 public static function boot()
21 {
22 parent::boot();
23
24 static::hasManySaving(function ($parent, $related) {
25 Log::info("Saving user's country {$parent->name}.");
26 });
27
28 static::hasManySaved(function ($parent, $related) {
29 Log::info("User's country is now set to {$parent->name}.");
30 });
31 }
32}

And the inverse of the relationship with this package might look like the following:

1namespace App\Models;
2
3use Illuminate\Database\Eloquent\Model;
4use Chelout\RelationshipEvents\Concerns\HasBelongsToEvents;
5
6class User extends Model
7{
8 use HasBelongsToEvents;
9
10 /**
11 * Get the country associated with the user.
12 */
13 public function country()
14 {
15 return $this->belongsTo(Country::class);
16 }
17
18 protected static function boot()
19 {
20 parent::boot();
21
22 static::belongsToAssociating(function ($relation, $related, $parent) {
23 Log::info("Associating country {$parent->name} with user.");
24 });
25
26 static::belongsToAssociated(function ($relation, $related, $parent) {
27 Log::info("User has been assosiated with country {$parent->name}.");
28 });
29 }
30}

Using an overloaded associate() method, you can fire two events belongsToAssociating and belongsToAssociated:

1$country = App\Models\Country::first();
2
3$user = factory(User::class)->create([
4 'name' => 'John Smith',
5]);
6
7// Assosiate user with country
8// This will fire belongsToAssociating and belongsToAssociated events
9$user->country()->associate($country);

Learn More

The package has documentation for each trait and association type. Check out the package on GitHub at chelout/laravel-relationship-events.

Filed in:

Paul Redmond

Full stack web developer. Author of Lumen Programming Guide and Docker for PHP Developers.