Laravel 的模型之一未调用已删除的方法
Posted
技术标签:
【中文标题】Laravel 的模型之一未调用已删除的方法【英文标题】:Deleted method is not called on one of Laravel's models 【发布时间】:2021-12-04 21:08:21 【问题描述】:我正在使用带有 Voyager 管理面板的 Laravel 6。
我有两个不同的 Laravel 模型,我正在从 Voyager 管理面板中删除它们的项目,删除对两个模型的项目都很有效。
我想在模型删除时添加一些操作,因此我将此代码添加到两个模型中。 它适用于模型 A 但不适用于模型 B,我不知道为什么以及如何调试和修复它。
public static function boot()
parent::boot();
static::deleted(function($model)
someaction();
);
我发现的模型之间仅有的两个区别
-
模型 B 在其数据库迁移中具有级联删除
Model B 扩展了 \TCG\Voyager\Models\User
【问题讨论】:
请在您的问题中添加minimal reproducible example,包括有关相关模型、数据库结构以及最重要的您认为应该触发此事件的操作的信息. 【参考方案1】:我建议使用 laravel 的观察者来触发事件的某些代码,包括创建、更新、删除...
您可以在此处查看参考:https://laravel.com/docs/8.x/eloquent#observers
创建观察者后,将此代码添加到模型中:
public static function boot()
parent::boot();
MyModel::observe(MyModelObserver::class);
【讨论】:
【参考方案2】:您提到模型 B 在迁移时具有级联删除功能。这很可能是原因。删除事件不会被触发,因为删除发生在数据库级别而不是通过 Laravel。如果您仍然需要此事件,您可以通过应用程序处理删除,而不是级联删除。另一种方法是观察外键模型上的删除事件,然后处理您的函数。 Here's a related question 这可能会有所帮助。
要进一步确认是否是级联删除的原因,请尝试通过应用 (ModelB::find(1)->delete()
) 从 Model B 中手动删除某些内容。
除此之外,如果你是deleting records through query (ModelB::where('something', 1)->delete()
),它也不会被解雇。
【讨论】:
【参考方案3】:你必须创建一个事件绑定类:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use App\Item;
use Log;
class ItemEvent
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function itemDeleted(Item $item)
Log::info("Item Deleted Event Fire: ".$item);
在事件提供者上注册:
class EventServiceProvider extends ServiceProvider
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
'App\Events\Event' => [
'App\Listeners\EventListener',
],
'item.deleted' => [
'App\Events\ItemEvent@itemDeleted',
]
];
/**
* Register any events for your application.
*
* @return void
*/
public function boot()
parent::boot();
你可以像这样在启动模型上测试它:
class Item extends Model
protected $fillable = ['name', 'price'];
public static function boot()
parent::boot();
static::deleted(function($item)
\Log::info('Item Deleted Event:'.$item);
);
static::deleting(function($item)
\Log::info('Item Deleting Event:'.$item);
);
【讨论】:
你能解释一下为什么这应该有效吗?我所拥有的模型之间有什么区别? 不同的是你必须创建一个事件来处理模型触发事件并注册它们,所以不需要在启动方法上处理它,我这里只是为了记录并保证事件项删除正在触发以上是关于Laravel 的模型之一未调用已删除的方法的主要内容,如果未能解决你的问题,请参考以下文章
从模型的访问器抛出自定义Laravel异常时未调用方法render()
调用未定义的方法 App\Models\Car::setCreatedAt() - Laravel - 5.8.16