Laravel Observer的deleted()函数如何使用已删除模型数据?
解决Laravel Observer删除后无法获取模型数据的问题
下面给你几个可行的解决思路:
1. 传递模型必要属性而非整个实例
既然deleted方法触发时模型已从数据库删除,你可以在deleted方法中先提取任务所需的关键数据,将这些数据直接传给任务,而非依赖整个模型对象。
修改Observer的deleted方法:
public function deleted(Company $company) { // 提取外部API需要的标识符 $customerIdentifier = $company->collection_identifier; dispatch(new ExternalAPIDeleteCustomer($customerIdentifier)); }
然后调整ExternalAPIDeleteCustomer任务的逻辑:
class ExternalAPIDeleteCustomer implements ShouldQueue { private $customerIdentifier; public function __construct(string $customerIdentifier) { $this->customerIdentifier = $customerIdentifier; } public function handle() { $response = Http::withHeaders([ 'X-Api-Key' => 'API-KEY', 'X-Api-Secret' => 'API-SECRET' ])->delete("https://EXTERNAL.API/v1/customers/{$this->customerIdentifier}"); } }
这种方式让任务不再依赖已删除的模型实例,直接使用提前提取的标识符即可完成API调用。
2. 启用软删除(业务场景允许的话)
如果你的业务可以接受软删除(仅标记记录为已删除,而非物理删除),可以给Company模型启用软删除特性:
首先在模型中引入软删除Trait:
use Illuminate\Database\Eloquent\SoftDeletes; class Company extends Model { use SoftDeletes; }
然后生成并执行软删除迁移:
php artisan make:migration add_deleted_at_to_companies_table --table=companies
迁移文件内容:
public function up() { Schema::table('companies', function (Blueprint $table) { $table->softDeletes(); }); } public function down() { Schema::table('companies', function (Blueprint $table) { $table->dropSoftDeletes(); }); }
启用软删除后,执行删除操作时模型不会被物理删除,deleted方法触发时你仍能正常访问模型的所有属性,原任务代码无需修改即可正常运行。后续若需要清理软删除记录,可通过定时任务执行Company::onlyTrashed()->forceDelete()。
3. 自定义Nova的删除动作
既然Laravel Nova不支持触发deleting观察者方法,你可以直接在Nova的Company资源中自定义删除逻辑,先分发任务再执行删除:
修改Nova的Company资源文件:
use Laravel\Nova\Actions\Action; use Laravel\Nova\Fields\ActionFields; use Laravel\Nova\Http\Requests\NovaRequest; class Company extends Resource { // ... 其他资源配置代码 public function actions(NovaRequest $request) { return [ Action::make('删除客户') ->confirmText('确定要删除这个客户吗?') ->confirmButtonText('删除') ->cancelButtonText('取消') ->handle(function (ActionFields $fields, $models) { foreach ($models as $model) { // 先分发删除任务(此时模型未删除,可正常获取属性) dispatch(new ExternalAPIDeleteCustomer($model)); // 再执行模型删除 $model->delete(); } return Action::message('客户已删除并同步到外部API'); }) ->destructive(), ]; } // 隐藏Nova默认的删除按钮,强制使用自定义动作 public function authorizedToDelete(Request $request) { return false; } }
这样用户在Nova后台删除记录时,会先触发API同步任务,再执行模型删除,完美避开deleted方法无法获取模型数据的问题。
内容的提问来源于stack exchange,提问作者Louis Sallée-Delille
相关产品推荐
相关产品推荐

