David B
David B

Reputation: 460

Laravel customize create() method on model

I'm trying to extend the create() method on a model so that every time you call a create() it does some stuff before insert the row.

For example I have a Balance model, which has fields amount and ending_balance. I want to be able to only specify the amount when create() and then have the ending_balance automatically calculated within the model (ie by looking up the previous ending_balance)

I'd also like to be able to put all the create logic within a DB::transaction() so that I can lock the rows while doing the calculations.

I've added this to my model, but it never hits the dd() when creating.

class Balance extends Model
{
    use HasFactory;

    public static function create(array $attributes = [])
    {
        dd($attributes);
        // Calculate the ending_balance here 

        return parent::create($attributes);
    }
}

Upvotes: 0

Views: 1645

Answers (1)

piotr.jura
piotr.jura

Reputation: 899

You might want to use Model events.

This link describes how to do it using closures: https://laravel.com/docs/8.x/eloquent#events-using-closures

the "created/creating" event might be what you are looking for. If things need to be recalculated, take a look at the updating/updated events.

 class Balance extends Model
    {
        protected static function booted()
        {
            static::created(function ($user) {
                // Calculate the fields value here
            });
        }
    }

I personally think overriding the create method is a little bit odd, and I've never seen anyone doing it. It might be not obvious for your teammates too. Just stick with events.

Another question was - how to do things in a transaction. Answer: use Laravel DB facade to run code in a transaction:

https://laravel.com/docs/8.x/database#database-transactions

DB::transaction(function () {
    Balance::create([...]);
    OtherMode::create([...]);
});

This will commit the transaction after the last line in the closure.

You can also manually control transactions:

DB::beginTransaction();
DB::rollBack();
DB::commit();

Upvotes: 3

Related Questions