Laravel关联创建时如何按参数屏蔽Observer的created事件
解决Laravel中根据参数屏蔽观察者Created事件的问题
问题描述
需要根据传入的link_social参数控制CreatorObserver的created()方法触发逻辑:当参数为false时,阻止该方法执行。
最初编写的代码如下:
$role = $request->role == 'creator' ? 'creator' : 'sponsor'; if($request->link_social == true){ $user = Auth::user()->$role()->create([ 'name' => $request->safe()->name, 'about' => $request->safe()->about, 'account_plan_id' => $accountPlan->id, ]); } else{ $user = Auth::user()->$role()->create([ 'name' => $request->safe()->name, 'about' => $request->safe()->about, 'account_plan_id' => $accountPlan->id, ])->saveQuietly(); }
执行时出现错误:
"message": "Call to undefined method App\Models\Creator::saveQuitely()"
且即使参数为false,CreatorObserver的created()事件依然会触发,该事件会在SocialPlatform表中创建记录。期望实现类似$user->role->create()->saveQuietly()的效果。
相关代码片段
CreatorObserver
class CreatorObserver { /** * Handle the Creator "created" event. * * @param \App\Models\Creator $creator * @return void */ public function created(Creator $creator) { if ($creator->user->social_identifier['platform'] === PlatformType::Google->value) { $youtube = new YoutubeService($creator->user->social_identifier); SocialPlatform::createFor($creator, $youtube); } } }
User模型
public function sponsor() { return $this->hasOne(Sponsor::class); } public function creator() { return $this->hasOne(Creator::class); }
Creator模型
class Creator extends Model { use HasFactory; protected $guarded = []; public function user() { return $this->belongsTo(User::class); } public function socialPlatforms() { return $this->hasMany(SocialPlatform::class); } }
解决方案
错误原因
- 拼写错误:调用的
saveQuitely()是拼写错误,正确方法名为saveQuietly()(注意是quietly)。 - 逻辑错误:
create()方法会直接触发created事件并返回已保存的模型实例,此时调用saveQuietly()无意义,模型已完成创建。
正确实现方式
方式一:用withoutEvents()临时禁用事件
通过withoutEvents()闭包包裹创建逻辑,临时跳过所有模型事件(包括观察者的created方法):
$role = $request->role == 'creator' ? 'creator' : 'sponsor'; if($request->link_social == true){ $user = Auth::user()->$role()->create([ 'name' => $request->safe()->name, 'about' => $request->safe()->about, 'account_plan_id' => $accountPlan->id, ]); } else{ // 临时禁用模型事件 $user = Creator::withoutEvents(function () use ($request, $accountPlan) { return Auth::user()->creator()->create([ 'name' => $request->safe()->name, 'about' => $request->safe()->about, 'account_plan_id' => $accountPlan->id, ]); }); }
若
$role可能为sponsor且对应有观察者,需根据实际情况调整闭包内的模型类。
方式二:在观察者内部添加判断逻辑
给Creator模型添加临时属性,在观察者中根据属性控制逻辑:
- 创建模型时传递标识:
$role = $request->role == 'creator' ? 'creator' : 'sponsor'; $attributes = [ 'name' => $request->safe()->name, 'about' => $request->safe()->about, 'account_plan_id' => $accountPlan->id, ]; // 添加临时属性,不会存入数据库 $creator = new Creator($attributes); $creator->skip_link_social = !$request->link_social; Auth::user()->creator()->save($creator);
- 修改
CreatorObserver的created方法:
public function created(Creator $creator) { // 标记为跳过则直接返回 if (isset($creator->skip_link_social) && $creator->skip_link_social) { return; } if ($creator->user->social_identifier['platform'] === PlatformType::Google->value) { $youtube = new YoutubeService($creator->user->social_identifier); SocialPlatform::createFor($creator, $youtube); } }
方案推荐
- 仅需临时跳过观察者事件,选方式一更简洁;
- 需要灵活扩展逻辑判断,选方式二扩展性更强。
内容的提问来源于stack exchange,提问作者Vince
相关产品推荐
相关产品推荐

