-
Notifications
You must be signed in to change notification settings - Fork 11.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[5.2] firstOrCreate will not create new db rows when a model has a mutator #14656
Conversation
@@ -233,6 +233,8 @@ public function findOrNew($id, $columns = ['*']) | |||
*/ | |||
public function firstOrNew(array $attributes) | |||
{ | |||
$attributes = $this->model->newInstance()->fill($attributes)->attributesToArray(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't fill()
only works if we un-guard the model?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.