You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

解决方案

错误原因

  1. 拼写错误:调用的saveQuitely()是拼写错误,正确方法名为saveQuietly()(注意是quietly)。
  2. 逻辑错误: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模型添加临时属性,在观察者中根据属性控制逻辑:

  1. 创建模型时传递标识:
$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);
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 12:57:06