-
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 doesn't work as expected #14649
Comments
I think the mutator shouldn't affect the query, I mean you may decide to change the mutator at some point |
Well, I can change it, but in this case I would expect to get record with exact data I would put into database and either I'm getting totally different record or I'm getting created new record over and over instead of using correct one. Now the only way is to apply mutator manually or putting the code I put here outside |
I personally believe queries should stay decoupled from mutators, think of all the drama that could happen if you provide I think for use case |
Well, but mutators are only kind of helpers. So when I create user object with name Also at the moment:
and
would work totally different although they both in theory should return with user PS. Obviously the implementation I showed above also should be a bit different - instead of |
ok I just want to get some clarity on this issue or see if Im doing something wrong here. So I tried to replicate what you were saying and here is what happened for me.
Is this the error you were talking about before? Screenshot below of step 6 |
I was able to fix this issue with the following code. public function firstOrCreate(array $attributes)
{
$attributes = $this->model->newInstance()->fill($attributes)->attributesToArray();
if (! is_null($instance = $this->where($attributes)->first())) {
return $instance;
}
$instance = $this->model->newInstance($attributes);
$instance->save();
return $instance;
} The |
@miscbits Yes, this is the problem, but I don't know if your implementation is correct. In this case I think attributes will be mutated twice and in the sample mutator I showed it might cause the problem because you can finish with record with |
hmmm @mnabialek I think I see the issue. The checks here return ok if you return a model but when you create a new one it will mutate the attributes twice. It seems that I need to just make a second variable and not edit the contents of $attributes |
I do agree that this is a strange behavior however calling the mutators may lead to unexpected results. Also this is inconsistent, IMO we should remove the mutators and create a flag like |
I don't know, if we apply mutator on querying it'll be a bit strange.
Will return a user with name |
Also mutators can be dynamic, right?
How would you deal with that? |
@themsaid You're right, we can't apply the mutators when querying however at least firstOrNew and firstOrCreate should be modified to apply the mutators before searching them or not apply the mutators when inserting. As of now if you have the Also notice that the submitted PR is targeting the 5.2 branch so at least we should close that and target the 5.3 if there will indeed have a change on these functions. |
What about mutators with dynamic assignment?
As in the PR That's why I say the behaviour is not expected at all. |
The first or create method already applies the mutator when inserting hence the glitch that occurs. I think right now the unexpected behavior is the mutator creating an instance when it already exists in the data. I was wondering today if there would be contradictions with getter methods at this point though. Might be worth looking into. Just quickly thinking through it Idk if there is a use case that would be affected by the getter methods but it would be worth testing |
I think that the taylor's suggestion on that PR will also fix the behavior described in your mutator example. |
@fernandobandeira yes I believe that is correct. I just tested it before sending the commit up and didn't get a glitch anymore. |
i have a question about firstOrCreate, is there a way to NOT create a new record when the value is empty or null? I have a value which is an empty string and firstOrCreate its creating an new entry with an empty field for 'name'. my code looks like this |
In my opinion
firstOrCreate
method doesn't work as expected. It does not apply only for this method but probably also for other Builder methods.As example let's use it like this:
(and assume we have only
id
andname
fields inusers
table) for table database.When we run this multiple times, we will always have only one user created with
test
name.But now, let's add mutator to
User
model like so:let's again make table empty.
And what happens now - each time we run the code we have new record created because mutator is not used for verifying the record existence. It might get even worse, because If we has one record before creating mutator, each time we run the code we would have returned this record however in fact it would not be what we expect.
As a quick fix I think in
firstOrCreate
this piece of code:should be changed in something like this:
what would make the mutators are applied now to verifying records existence.
However it would be a quite breaking change (though I think it's the way it should always work this way) so probably it should be put into upcoming 5.3 release if decided it's a bug.
The text was updated successfully, but these errors were encountered: