Search code examples
phplaravellaravel-9observers

Laravel mute Observer event in chaining relationship create method


I have a question on how to mute the observer's method based on the parameters I pass. I have a parameter of link_social and if it is set to false I wanted the observer to not trigger the created() function.

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

The User model has a relationship method creator and the observer is from that model named CreatorObserver

but I got this "message": "Call to undefined method App\\Models\\Creator::saveQuitely()"

error when saving (edited) and still it triggers the created() event in the creator observer which is saving a record in another table.

I am trying to do someting like $user->role->create()->saveQuitely()

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 model

    public function sponsor()
    {
        return $this->hasOne(Sponsor::class);
    }

    public function creator()
    {
        return $this->hasOne(Creator::class);
    }

Creator Model

class Creator extends Model
{
    use HasFactory;

    protected $guarded = [];

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    public function socialPlatforms()
    {
        return $this->hasMany(SocialPlatform::class);
    }
}

Solution

  • saveQuietly/ createQuietly shouldn't be chained after create as the create function will dispatch the creation events which is handled by the observer created function. to prevent the model from dispatching the event it can be done in one of two ways: using createQuietly

    $user = Auth::user()->$role()->createQuietly([
            'name' => $request->safe()->name,
            'about' => $request->safe()->about,
            'account_plan_id' => $accountPlan->id,
        ]);
    

    or use the model withoutEvents function

    $user = Model::withoutEvents(function () use ($request, $role, $accountPlan) {
            return Auth::user()->$role()->create([
                'name' => $request->safe()->name,
                'about' => $request->safe()->about,
                'account_plan_id' => $accountPlan->id,
            ]);
        });
    

    base Model was used as the created model can be Creator or Sponsor if the model class is known we can replace Model::withoutEvents to be YourModelName::withoutEvents