Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eloquent event is not firing

Tags:

php

eloquent

I want to set the password when it changes in my User model. So I'm using boot method of the model:

<?php
namespace App\Model;

class User extends \Illuminate\Database\Eloquent\Model
{
    protected $table = 'users';

    public static function boot()
    {
        //die('here'); // this happens
        User::saving(function ($user) {
            //die('here'); // this doesn't happen
            if ($user->isDirty('password')) {
                $user->password = // hash password...
            }
        });
    }
}

I'm using the save() method on the model to create the entry in the data base, apparently this should fire the creating event. I've emptied the database table to ensure that a new row is being creating (it is), this event does not fire - and my password is raw un-ecrypted. By the way, I'm using illuminate/database ^5.2 in my app (not Laravel).

UPDATE - capsule initialization

$capsule = new Illuminate\Database\Capsule\Manager;
$capsule->addConnection([
    'driver' => 'mysql',
    'host' => 'localhost',
    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix' => '',
    'database' => 'mydb',
    'username' => 'myuser',
    'password' => 'mypass',
]);
$capsule->bootEloquent();
like image 913
Martyn Avatar asked Dec 08 '22 23:12

Martyn


1 Answers

If you want your events to work, you need to setup an event dispatcher for the capsule.

First, you will need to add illuminate/events to your dependencies. Add "illuminate/events": "5.2.*" to your composer.json file:

"require": {
    // other requires...
    "illuminate/events": "5.2.*"
},

Next, you'll need to setup the event dispatcher on the capsule. Make sure you do this before your call to bootEloquent(). From the docs:

// new capsule...

// add connection...

// Set the event dispatcher used by Eloquent models... (optional)
use Illuminate\Events\Dispatcher;
use Illuminate\Container\Container;
$capsule->setEventDispatcher(new Dispatcher(new Container));

// Setup the Eloquent ORM... (optional; unless you've used setEventDispatcher())
$capsule->bootEloquent();

Now you should be good to go.

While not related, I also wanted to point out that your boot method should make sure to call parent::boot(); before it does anything else (like setting up events).


Optional solution

If this is the only thing you're trying to do with the events, you can skip this altogether by setting up a mutator function for your password attribute. The mutator method will be called any time you assign a value to the mutated attribute (i.e. $user->password = "hello").

To do this, just add the following function to your User model:

public function setPasswordAttribute($value) {
    $this->attributes['password'] = bcrypt($value);
}
like image 126
patricus Avatar answered Jan 01 '23 03:01

patricus