优美的事件未触发

6

我希望在用户模型中更改密码时设置密码。因此,我正在使用模型的boot方法:

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

我在模型上使用save()方法创建数据库记录,理论上这应该触发创建事件。我已经清空了数据库表以确保正在创建新行(确实是如此),但该事件没有被触发 - 而我的密码是原始未加密的。顺便说一句,我的应用程序中使用的是illuminate/database ^5.2(而不是Laravel)。

更新 - 胶囊初始化

$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();

你在胶囊上设置了事件分发器吗?能展示一下你的胶囊初始化代码吗? - patricus
嗨,感谢回复。嗯,据我所知没有。我已经更新了我的帖子并初始化了胶囊。 - Martyn
2个回答

15
如果您想让您的事件正常工作,您需要为胶囊设置一个事件分发器。
首先,您需要将"illuminate/events"添加到您的依赖项中。将`"illuminate/events": "5.2.*"`添加到您的`composer.json`文件中:
"require": {
    // other requires...
    "illuminate/events": "5.2.*"
},

接下来,您需要在胶囊上设置事件分发器。确保在调用bootEloquent()之前完成此操作。参见文档

// 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();

现在你应该可以开始了。

虽然没有关联,但我也想指出你的boot方法应该在做任何其他事情(如设置事件)之前确保调用parent::boot();


可选解决方案

如果这是您与事件正在尝试完成的唯一事情,您可以通过为password属性设置变异器函数来完全跳过这个过程。当您分配值给变异属性时(即$user->password = "hello"),将调用变异方法。要做到这一点,只需在User模型中添加以下函数:

public function setPasswordAttribute($value) {
    $this->attributes['password'] = bcrypt($value);
}

非常好的答案,谢谢!是的,您的可选解决方案对于我的密码更好,在其他属性方面 boot() 方法现在也能很好地工作。我没有意识到我也必须使用 parent::boot(),知道了这点真不错。 - Martyn

2

我曾经遇到过同样的问题,这是我解决它的方法:

1 首先,我确保要求所有必要的软件包:

{
    "require": {
        "illuminate/database": "~5.2",
        "illuminate/events": "~5.2",
    }
} 

2 然后我必须正确设置我的数据库连接

use Illuminate\Database\Capsule\Manager as Capsule;

$capsule = new Capsule;

$capsule->addConnection([
    'driver'    => "driver",
    'host'      => "host",
    'database'  => "database",
    'username'  => "username",
    'password'  => "password",
    'charset'   => "charset",
    'collation' => "collation",
    'prefix'    => "prefix",
]);

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

// Make this Capsule instance available globally via static methods... (optional)
$capsule->setAsGlobal();

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

3 之后,我使用了Trait,因为它是清理模型的完美解决方案

trait ModelTrait{

    public static function bootModelTrait()
    {
        static::creating(function ($model) {
            // Create Event Here
        });
    }
}

4 然后我在每个模型中使用了这个特性

class User extends Eloquent
{
    use ModelTrait;

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接