Framework: [5.4] Model observer not called when model used with belongsTo

Created on 12 Feb 2017  路  5Comments  路  Source: laravel/framework

  • Laravel Version: latest
  • PHP Version: 7
  • Database Driver & Version: mysql 5.7

Description:

When i decrementing database value with belongsTo observer not working.

$order->offer->decrement('total_count', $order->amount);

```php
namespace AppObservers;

use AppModelsOffer;

class OfferObserver
{
public function updating(Offer $offer)
{ // not even called
if ($offer->total_count == 0) {
$offer->status = false;
}
}
}

in order model:
```php 
public function offer()
    {
        return $this->belongsTo(Offer::class, 'offer_id');
    }

in Offer model:

public static function boot()
    {
        parent::observe(new OfferObserver());
        parent::boot();
    }

Steps To Reproduce:

  1. Create 2 models with belongsTo relation.
  2. Create observer for child model
  3. Update child model from parent
  4. look what happened

Most helpful comment

Anyway not firing event when you really updating db also not desired affect, hope this logic will changed in future.

All 5 comments

Incrementing and decrementing a value doesn't fire the events because it's called directly on the query builder instance.

see here

Line 410: Will perform an increment or decrement of the chosen column for every row in your table, this is assuming you haven't loaded a model and are simply doing Order::decrement('total_count', $amount) for example.

Line 413: Will update the attribute on the model if one is loaded.

Line 415: Begins the update against that single row for your loaded model in your table.

Now.. the updated at timestamp is being updated so yes the model has been updated and you would probably expect a model event to be fired. But for the first case it's not possible as you don't have a model loaded, it will update every model (or row, however you want to look at it).

It could be possible to call the update method if the model does exist rather than via query builder, as this would fire the updated event. However, thats probably up for discussion as it will alter the method return type and might not be desired affect for some?

I would probably stick with this for now.

$order->offer->total_count = $order->offer->total_count - $order->amount;
$order->offer->save();

Anyway not firing event when you really updating db also not desired affect, hope this logic will changed in future.

For suggestions and feature requests please use the https://github.com/laravel/internals repo.

I have no idea why you closed an issue. It's not related to feature or suggestion, in my opinion it's bug.
increment/decrement functions are updating table and must call update event. I think everyone expects calling update event after update the table, no?

These events are eloquent events, that respond to eloquent acts, not table changes. There are many ways to make changes to your data that doesn't fire the eloquent events. If you want an updating event to be fired then you'll need to use eloquent to perform the operation then save the instance. If you have a solution for the framework to handle this, maybe you could submit a pr.

Increment and decrement are there for convenience. If you need different functionality, it would be simple to drop a method on your model or build a simple trait for models you want to be able to increment and decrement.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

felixsanz picture felixsanz  路  3Comments

PhiloNL picture PhiloNL  路  3Comments

CupOfTea696 picture CupOfTea696  路  3Comments

iivanov2 picture iivanov2  路  3Comments

lzp819739483 picture lzp819739483  路  3Comments