Skip to content
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

[6.x] Add ->firstWhere eloquent method #31089

Merged

Conversation

calebporzio
Copy link
Contributor

A shortcut for ->where(...)->first()

Example: I'm fetching a user by email address:

// Before
User::where('emaill', 'foo@bar.com')->first();

// After
User::firstWhere('email', 'foo@bar.com');

My initial instinct was ->whereFirst, but 1. it's a breaking change, and 2. collections have a ->firstWhere.

Implementation Notes:

I only added this to the Eloquent builder for now. I thought I could just add it to the Query builder and everything would be fine, but I ran into some issues (the test I wrote was failing).

If it turns out people want this on the Query builder itself, could just copy it there. (or dig into the root problem, which probably has something to do with me not understanding the forwarding chain (and it's implications) well enough.

Thanks!

@calebporzio calebporzio changed the title Add ->firstWhere eloquent method [6.x] Add ->firstWhere eloquent method Jan 9, 2020
@SjorsO
Copy link
Contributor

SjorsO commented Jan 10, 2020

An added benefit here is that when using Laravel IDE-helpers, your IDE can understand what type is being returned:

// Before:

/** @var User $user */
$user = User::where('email', 'foo@bar.com')->first();

// After:

// IDE knows the type without an annotation
$user = User::firstWhere('email', 'foo@bar.com');

@taylorotwell taylorotwell merged commit 9a302ff into laravel:6.x Jan 10, 2020
@taylorotwell
Copy link
Member

Might want to shoot a PR to the docs too. <3

@calebporzio
Copy link
Contributor Author

Done: laravel/docs#5716

@binaryk
Copy link
Contributor

binaryk commented Jan 11, 2020

Good to have it, but what about using traditional collection first with a condition inside?

Model::first('email', 'foo@bar.com'); 

I know Enumerable has firstWhere as well, but IMHO it doesn't bring much value since first does the same.

@mbougarne
Copy link

Model::first('email', 'foo@bar.com'); 

It doesn't work the same, the new method will give an instance of the model based on $key = $value in the other hand public function first($columns = ['*']) it will return just the selected columns, in your example it'll be "email" => "foo@bar.com" you can pass array to get more columns Model::first(['email', 'username'])

It seems to me that's working like this User::all()->firstWhere('id', '!=', 1)

@binaryk
Copy link
Contributor

binaryk commented Jan 11, 2020

Right @mbougarne , but that method could be simply improved by checking argument number for example. If we have more than 1 argument, than we assume we passed a condition -> so it will return the first entry matching that condition. The benefit is that we maintain the collection pattern.

@ahinkle
Copy link
Contributor

ahinkle commented Jan 22, 2020

after using this more and more I'm finding myself wanting a ->where(...)->get() shortcut. getWhere('email', 'foo@bar.com')? Thoughts on implementation? Not sure if it would battle with the getters. Another option could be allWhere().

I can create a PR if anyone else might find it useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants