[5.2] firstOrCreate will not create new db rows when a model has a mutator#14656
Conversation
| */ | ||
| public function firstOrNew(array $attributes) | ||
| { | ||
| $attributes = $this->model->newInstance()->fill($attributes)->attributesToArray(); |
There was a problem hiding this comment.
Wouldn't fill() only works if we un-guard the model?
There was a problem hiding this comment.
yes if someone tries to use variables that aren't fillable, but if that's the case it should not create a new model anyway because those attributes are guarded
There was a problem hiding this comment.
not create a new model anyway because those attributes are guarded
Mass assignment exception doesn't occur when you call save(), it occur within fill() https://github.com/laravel/framework/blob/5.2/src/Illuminate/Database/Eloquent/Model.php#L439-L457
You might want to look at forceFill().
There was a problem hiding this comment.
See the newest commit. Instead of forceFill() I just moved the instance line to the top of the method
$instance = $this->model->newInstance($attributes);
This was already in the method beforehand so it should not change the behavior of the method and still fix the bug that was reported.
…nt error thrown anymore
…en soft deleted user is called from instance
|
Accordingly public function firstOrCreate(array $attributes)
{
$instance = $this->firstOrNew($attributes);
$instance->save();
return $instance;
}I understand that it's not related to this PR, but just noticed code duplication. |
|
👍 This is actually changing the behavior of the function, should it really go to 5.2? |
|
How would this change handle the case of mutators with dynamic data?
|
|
I think in general this makes sense as an idea but I don't agree with using Running |
|
@taylorotwell I was talking about the possibility of that in the bug report cause I was thinking about it today. I haven't had time to look/test that possibility. I'll send up a new commit momentarily to this PR. |
|
@fernandobandeira good idea and will do. |
|
@fernandobandeira nevermind. you're just sending in an ID for the find function, so why would this fix need to be implemented? (unless someone put a mutator on the id of course) |
|
@themsaid I think the results would be expected really. It might not be if you forget you wrote that mutator but if a dev is aware of the mutators in their model class it should be apparent why results like that may come about. It's still better than the behavior that allows you to create more than one instance of the same object in your database. |
…tator (laravel#14656) * firstOrCreate will not create new db rows when a model has a mutator * removed changes to firstOrCreate in Relationships * fixed firstOrCreate mutating attribute twice * replicated behavior of Builder before intial change. No mass assignment error thrown anymore * fixed typo * changed Builder edit to pass test. firstOrNew not creating null id when soft deleted user is called from instance * white space issue * addedAttributesToArray to declaration of mutatated Attributes * use getAttributes instead of getAttributesArray
fixes issue #14649
When using the firstOrCreate function, the attributes passed in will be used to search for the value in the database even if the model has mutators which will change the values that should be in attributes. This change fills a model and then runs the
attributesToArray()method to get the true value of the attributes needed to see if this model is the first in the database.