将一个模型传递一个到事件监听器里,为什么模型的getChanges、isDirty、isClean 、 wasChanged都为空?

1. 运行环境

1). 当前使用的 Laravel 版本?

Laravel Framework 10.31.0

2). 当前使用的 php/php-fpm 版本?

PHP 版本:PHP 8.1.21

php-fpm 版本:PHP 8.1.21

3). 当前系统

Ubuntu 22.04

4). 业务环境

开发环境

2. 问题描述?

下面是代码片段,运行php artisan debug

<?php
// 第一次dump
namespace App\Console\Commands;

use App\Models\Device\AlmDevice;

use Illuminate\Console\Command;


class Debug extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'debug';

    public function handle()
    {
        $almDevice = AlmDevice::find(1);
        $almDevice->update(['memo' => '12345021q6070']);
        dump($almDevice->getChanges());
        event(new \App\Events\Device\Alm\UpdatedEvent($almDevice));
    }
}
<?php
// 第二次dump
namespace App\Events\Device\Alm;

use App\Events\BaseEvent;
use App\Models\Device\AlmDevice;

class UpdatedEvent extends BaseEvent
{
    public AlmDevice $almDevice;

    /**
     * Create a new event instance.
     */
    public function __construct(AlmDevice $almDevice)
    {
        parent::__construct();
        $this->almDevice = $almDevice;
        dump($almDevice->getChanges());
    }
}
<?php

namespace App\Providers;

use App\Listeners\Device\AlmSyncSubscribe;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

class EventServiceProvider extends ServiceProvider
{
    /**
     * The event to listener mappings for the application.
     *
     * @var array<class-string, array<int, class-string>>
     */
    protected $listen = [
        \App\Events\Device\Alm\UpdatedEvent::class => [
            [AlmSyncSubscribe::class, 'onDeviceUpdated'],
        ]
    ];

    /**
     * Register any events for your application.
     */
    public function boot(): void
    {
        //
    }

    /**
     * Determine if events and listeners should be automatically discovered.
     */
    public function shouldDiscoverEvents(): bool
    {
        return false;
    }
}
<?php
// 第三次dump
namespace App\Listeners\Device;

use App\Events\Device\Alm\UpdatedEvent;

class AlmSyncSubscribe extends ShouldQueue
{
    public function onDeviceUpdated(UpdatedEvent $event)
    {
        $almDevice = $event->almDevice;
        dump($almDevice->getChanges());
    }
}

3. 您期望得到的结果?

我期望是在第三次dump可以输出模型变更的属性

4. 您实际得到的结果?

array:2 [
  "update_time" => "2023-11-20 17:24:22"
  "memo" => "123450213q61070"
] // app/Console/Commands/Debug.php:26
array:2 [
  "update_time" => "2023-11-20 17:24:22"
  "memo" => "123450213q61070"
] // app/Events/Device/Alm/UpdatedEvent.php:19
[] // app/Listeners/Device/AlmSyncSubscribe.php:12
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
最佳答案

因为你的模型在派发任务时会因为 SerializesModels 这个 Trait 进行序列化,最后在消费的时候,再重新获取模型

If your queued job accepts an Eloquent model in its constructor, only the identifier for the model will be serialized onto the queue. When the job is actually handled, the queue system will automatically re-retrieve the full model instance and its loaded relationships from the database. This approach to model serialization allows for much smaller job payloads to be sent to your queue driver.

所以,其实你后面 AlmSyncSubscribe 里面其实是新查询到的一个模型,自然不存在这些变化。如果你需要这些变化,那你就要在派发的时候,单独取出来组装进去。

另外这也有一个值得思考的就是,在队列处理到这一行数据的时候,很可能它已经发生过变化了。

5个月前 评论
讨论数量: 3

如果是从队列取出来的话这是正常的, 毕竟它要先序列化到队列服务,如果没有实现对应的方法可能就无法保存变更的属性

5个月前 评论

update方法走的是sql更新并不是模型的更新,试试用save方法,给属性赋值后再save看看

5个月前 评论

因为你的模型在派发任务时会因为 SerializesModels 这个 Trait 进行序列化,最后在消费的时候,再重新获取模型

If your queued job accepts an Eloquent model in its constructor, only the identifier for the model will be serialized onto the queue. When the job is actually handled, the queue system will automatically re-retrieve the full model instance and its loaded relationships from the database. This approach to model serialization allows for much smaller job payloads to be sent to your queue driver.

所以,其实你后面 AlmSyncSubscribe 里面其实是新查询到的一个模型,自然不存在这些变化。如果你需要这些变化,那你就要在派发的时候,单独取出来组装进去。

另外这也有一个值得思考的就是,在队列处理到这一行数据的时候,很可能它已经发生过变化了。

5个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!