It's finally time that I understood this concept, because I still don't get some of the cases.
Question 1) what does save()
return? is it always boolean or does it throw exceptions sometimes?
Question 2) I am not using any event model. So I don't think save()
will return false at any time. So it will return true or throw the exception? am I right?
Question 3) If I have something like this:
DB::beginTransaction();
try{
$model1 = new Type();
$model1->test = 'great';
$model1->save();
$model2 = new Type();
$model2->test2 = 'awesome';
$model2->save();
DB::commit();
}catch(Exception $e){
DB::rollBack();
}
Is it possible that save doesn't happen but it doesn't throw the exception? I don't have any events in these models.
Question 4) if the answer for the question 3 is 'no it's not possible', then why do i need to use saveOrFail()
I'd really appreciate that since I really couldn't find anything that deeply explains what I am asking.
Save can be used to both create a new Record and update a existing record . Whereas create is used to create a new record by providing all required field at one time .
save() method is used both for saving new model, and updating existing one. here you are creating new model or find existing one, setting its properties one by one and finally saves in database.
To quietly save a model in Laravel you can make use of the "saveQuietly" method available to each model instance. ->saveQuietly();
Question 1) save()
can indeed throw exceptions. For example, if you create a model with a decimal column, e.g. 'cost', and try to save a string value in that column, both save()
and saveOrFail()
will throw an exception. Demo:
>>> $item->cost = 'asdas';
>>> $item->save();
Illuminate/Database/QueryException with message 'SQLSTATE[HY000]: General error: 1366 Incorrect decimal value: 'asdas' for column 'cost' at row 1 (SQL: update ...
Question 2) Looking through the source, it looks like save()
will only return false
when firing either the saving
, updating
or creating
events returns false
.
Since you haven't defined any event listeners, theoretically yes, you should only ever receive true
or an exception will be thrown.
Question 3) If you're not listening to events then no, it's not possible (at least not probable). The save would only not have happened if there was an exception thrown.
Question 4) Since saveOrFail()
just wraps save()
in a transaction, its use is to keep the database consistent if any exceptions were raised during the save()
function. saveOrFail()
ensures that if there were any exceptions raised during save()
, the model would not have been saved. save()
alone would not be able to guarantee that the model was not modified/saved if an exception was thrown.
Since you're already wrapping your code in a transaction, you don't need to use saveOrFail
.
For your use case, the best I can think of is to call save()
on all of your models in a single if-expression and to commit the transaction only if the expression is true
. That way you can cater for both when save()
returns false
or when it raises an exception. Like this:
DB::beginTransaction();
try {
$model1 = new Type();
$model1->test = 'great';
$model2 = new Type();
$model2->test2 = 'awesome';
if ($model1->save() && $model2->save()) {
DB::commit();
} else {
DB::rollBack();
}
} catch(Exception $e){
DB::rollBack();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With