Framework: Laravel observer fails with code -1

Created on 10 Jun 2019  路  3Comments  路  Source: laravel/framework

This issue is quite strange because of its illogicality. Here is my flow of creating a model:
Create model via mass assignment -> catch 'created' event in the observer -> calculate additional fields and update the newly created model.
Two out of three steps are working properly: I am able to catch the created event, but when it comes to saving the model something strange is happening. For instance, my test is running endlessly or it returns code -1. No errors, no stack trace, nothing. Here is my observer's code:

<?php

namespace App\Observers;

use App\Models\AdPrice;

class AdPriceObserver
{
    /**
     * Handle the models ad price "created" event.
     *
     * @param  \App\Models\AdPrice  $adPrice
     * @return void
     */
    public function created(AdPrice $adPrice)
    {
        $adPrice->update([
            'incremental_diff' => $this->computeIncrementalDiff($adPrice),
            'absolute_diff' => $this->computeAbsoluteDiff($adPrice)
        ]);
    }

    /**
     * Handle the models ad price "updated" event.
     *
     * @param  \App\Models\AdPrice  $adPrice
     * @return void
     */
    public function updated(AdPrice $adPrice)
    {
        $adPrice->update([
            'incremental_diff' => $this->computeIncrementalDiff($adPrice),
            'absolute_diff' => $this->computeAbsoluteDiff($adPrice)
        ]);
    }

    /**
     * Compute the incremental price difference.
     *
     * @param  \App\Models\AdPrice  $adPrice
     * @return float|null
     */
    protected function computeIncrementalDiff(AdPrice $adPrice)
    {
        /* @var \Illuminate\Support\Collection $prices */
        $prices = $adPrice->priceable->prices()->pluck('price');
        if ($prices->count() < 2) {
            return null;
        }

        $diff = ($prices[0] - $prices[1]) / $prices[1];

        return number_format($diff * 100, 2);
    }

    /**
     * Compute the absolute price difference.
     *
     * @param  \App\Models\AdPrice  $adPrice
     * @return float|null
     */
    protected function computeAbsoluteDiff(AdPrice $adPrice)
    {
        /* @var \Illuminate\Support\Collection $prices */
        $prices = $adPrice->priceable->prices()->pluck('price');
        if ($prices->count() < 3) {
            return null;
        }

        $diff = ($prices[0] - $prices->last()) / $prices->last();

        return number_format($diff * 100, 2);
    }
}

P.S. I am not including any other code(like observer registration in the service provider, etc.) because everything else works as it should.
P.S.S. The incremental_diff & absolute_diff fields are nullable and of type float. Also, they are cast to float in the model's file.

Most helpful comment

Your issue comes from an infinite recursion because of your update hook which call itself:

  1. $model->save()
  2. $observer->created($model) (triggers an update)
  3. $observer->update($model) (triggers an update)
  4. $observer->update($model) (triggers an update)
    And so on...

Edit: To fix this, I would set attributes manually in updating hook, btw you won't get an infinite loop.

All 3 comments

Your issue comes from an infinite recursion because of your update hook which call itself:

  1. $model->save()
  2. $observer->created($model) (triggers an update)
  3. $observer->update($model) (triggers an update)
  4. $observer->update($model) (triggers an update)
    And so on...

Edit: To fix this, I would set attributes manually in updating hook, btw you won't get an infinite loop.

You have an infinite update loop in the updated method of your observer.

Try something like this:

$adPrice->withoutEvents(function () use ($adPrice) {
    $adPrice->update([
        'incremental_diff' => $this->computeIncrementalDiff($adPrice),
        'absolute_diff' => $this->computeAbsoluteDiff($adPrice)
    ]);
});

Oh, I haven't even noticed that recursion... Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  3Comments

YannPl picture YannPl  路  3Comments

SachinAgarwal1337 picture SachinAgarwal1337  路  3Comments

PhiloNL picture PhiloNL  路  3Comments

Anahkiasen picture Anahkiasen  路  3Comments