Reputation: 460
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
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