-
Notifications
You must be signed in to change notification settings - Fork 11.7k
[9.x] Added the "for" method to the Eloquent Builder and Model #42467
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
Conversation
|
Nice job 👍🏻 |
|
@ash-jc-allen remember that draft PRs aren't reviewed |
|
Hey, @driesvints! Sorry, I completely forgot about that. I know that you won't review the PR whilst it's a draft, but from looking at the code examples in the PR description, would you say it's worth me carrying on with it? I wouldn't want to spend too much time on it if you don't think it's something that could get merged :) |
|
Hey @ash-jc-allen, I don't review PR's, only Taylor does. So please mark this as ready if you want a review from him. |
| */ | ||
| protected function mergeForeignKeys($attributes) | ||
| { | ||
| if (count($this->for)) { |
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.
$this->for being an array, is it really necessary to check its size with count?
foreach is enough, isn't it?
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.
Thanks for picking up on that for me. It was something I'd put in when I was first tinkering with another idea. But, I've taken that out now :)
|
I think that this is probably ready now for some kind of review. Apologies that this one has sat as a draft for so long! I've added some basic tests for each of the methods that I've updated too. I fully expect that I've probably missed something here or overlooked something. But, hopefully, it should be headed in the right direction and might be something that you think would be helpful for other developers. If it's something that you might consider merging, please let me know if you'd like me to make any changes 😄 |
|
When I saw the tweet about for on Eloquent I expected something to do with loops. Personally I prefer the explicit definition of the columns, but if this were to be merged I think I would prefer |
|
Awesome 👍 |
Disagree.. a model is a single entity.. not a collection. Also loop is not assumed for factories. I've thought "for" so many times. Happy to see a PR for it |
|
very Goooooooooood |
|
I think it's a great idea but I think the name method it's good to be |
|
IMO it would be great if the method also called $post->views()
->for($user)
->firstOrCreate([]);$video->templates()
->for($parentTemplate)
->firstOrCreate([], [
'elements' => $parentTemplate->elements,
]); |
|
So for methods like |
|
I've just added some extra assertions to the tests covering As far as I'm aware, the And then |
|
I'm just thinking: Comment::for($user)
->for(post)
->where('status', 'published')
->firstOrCreate([
'content' => 'abc',
]);It feels a bit ambiguous to me what this query would be. It feels like I would expect it to search for comments that belong to a given user and post that also have a given status and content. But, right now, it seems with this PR in its current state it would search for ANY comment with the given status and content - regardless of the user and post it belongs to. |
|
@taylorotwell Yeah the more that I look at your example, the more I agree with that. Based on that, do you want me to put together a quick change for the |
|
@taylorotwell that’s what I was thinking as well. It would probably be cool to have a combined method. But it also shouldn’t be limited to relations. Say, we have a Then the following query: Comment::query()
->having($user)
->having('status', 'published')
->first();Would be transformed into: Comment::query()
->where('user_id', $user->id)
->where('status', 'published')
->first();And the query as: Comment::query()
->having($user)
->having('status', 'published')
->create(['content' => $content]);Will get transformed into: Comment::query()
->create([
'user_id' => $user->id,
'status' => 'published',
'content' => $content,
]);So, this could become a pretty versatile helper for all create / update / firstOr / updateOr / get methods. |
|
I've updated this now so that if you use For example: Comment::for($user)
->for(post)
->where('status', 'published')
->firstOrCreate([
'content' => 'abc',
]);This would attempt to find a comment that belongs to I started adding the "for" functionality to the Hopefully, this should be working as expected 🙂 |
|
@ash-jc-allen can you summarize where you can and can't use |
|
Yeah, I've got a bit lost too because I've not looked at it in a few days. As far as I'm aware, it affects the following methods: Builder/Modelmake Comment::for($user)->make(...);create Comment::for($user)->create(...);forceCreate Comment::for($user)->forceCreate(...);update (the Comment::for($user)->update(...);firstOrNew (the Comment::for($user)->firstOrNew([], []);firstOrCreate (the Comment::for($user)->firstOrCreate([], []);updateOrCreate (the Comment::for($user)->updateOrCreate([], []);HasOneOrManymake $post->comments()->for($user)->make([...]);create $post->comments()->for($user)->create([...]);forceCreate $post->comments()->for($user)->forceCreate([...]);update (the $post->comments()->for($user)->update([...]);firstOrNew (the $post->comments()->for($user)->firstOrNew([...], [...]);firstOrCreate (the $post->comments()->for($user)->firstOrCreate([...], [...]);updateOrCreate (the $post->comments()->for($user)->updateOrCreate([...], [...]); |
|
I kinda think I will hold off on this for now. I worry it will be a bit too implicit and magical as to what is going on and will be hard to remember exactly what is happening in each scenario vs. just actually setting where clauses explicitly in the code. |
|
@taylorotwell That's a totally fair point, and I agree. It was a worth a shot and I'm glad I got chance to explore the idea and scratch an itch 😄 |
Hey! This PR proposes a new "for" method that can be used on models and in Eloquent queries.
I've marked this as a draft PR for the time being because I'm about half way through doing it. I still need to add the "for" method to the relationships (explained in more detail below). So, I didn't want to spend too much time working on it if you didn't think it would be worth merging in.
Context
This PR is inspired by the
whereBelongsTomethod that you can use in queries like:I like how it makes the code a lot more human-readable and avoids writing column names (e.g. -
user_id). So, I thought I'd give it a go and see if we could add something similar for creating/updating models.I chose the "for" name based on the fact that the functionality is similar to the "for" model factories.
Before
Excuse the super basic examples, but they should hopefully demonstrate my general point. Before my proposed method, you could have either of these example statements:
Or...
Or...
After
But the problem is that there's always still another ID field in the
createmethod if you're trying to make a relationship to more than one model. So, we could rewrite the queries as:Or...
At the moment, I've only got the
Model::for()and$model->for()approaches working for all the different query methods (as far as I can see, but I might have missed something). I haven't made a start on the relationships (e.g. -$model->relationship()->for()->create()) yet just in case this PR wasn't something that would get merged. If you think that this is something that would be valuable to other devs though, I'll carry on and get the relationships working too.Personally, I could see this being particularly useful feature and think it'd be a nice way of making our Laravel project codebases even cleaner! 😄
Apologies, by the way, if this sort of logic already exists and I've just completely missed it.
Hopefully, it's heading in a good direction, but it's no problem if you'd rather close the PR 😄