vincent15000's avatar

Strange behavior between find() and pluck()

Hello,

I have tested this, just to see what happens.

User::find(45)->pluck('email');

pluck is normally applied only on collections, but in the case I apply it on a model, it retrieves me all emails from the users table.

Why ?

I don't understand the logic.

Can anyone help me to understand ?

Thanks a lot.

V

0 likes
13 replies
tykus's avatar

Simple, the User instance (result of find) can also be used as a new Eloquent Builder.

1 like
vincent15000's avatar

@tykus I thought I would get an error because pluck should by applied only on collections.

Isn't pluck() a shorthand for get() and ... ?

tykus's avatar
tykus
Best Answer
Level 104

@vincent15000 there are several different pluck methods in the framework - Collection , Query Builder and Eloquent Builder.

The User instance itself has access to all of the Eloquent Builder methods even after a Model instance has been retrieved, so, logic like this will work even though it seems nonsensical.

User::find(1)->find(2)
1 like
tykus's avatar

If you simply need the email value for the User with ID 45, then:

User::where('id', 45)->value('email');
1 like
vincent15000's avatar

@tisuchi Yes that's ok for me. And I think that it's also possible to write ->get('email'). I never use this way, but I've already seen that somewhere.

tykus's avatar

@vincent15000 the result of pluck is different - a Collection of (email) strings - compared with get - a Collection of User object each only having email properties.

1 like
tykus's avatar

@tisuchi my point was that the result is different - get returns User objects in a Collection; Eloquent Builder's pluck does not.

1 like
Snapey's avatar

The bit not explained is that some functions are 'terminating' for the query builder. first(), find(), get(), paginate() and pluck() and I am sure there are more, all terminate the query builder and run the query.

After find() you end up with a single model against which you are trying to run pluck(), and since it is not a collection, you end up running the query builder pluck against the model the same as if you had run User::pluck('x')

On the other hand, if you had run get()->pluck() you would be calling pluck against the collection and therefore using the collection pluck command not the query builder.

1 like
Snapey's avatar

@vincent15000 sure. it will return all the emails of the collection returned by get.

User::get()->pluck('email')

is no different to

User::pluck('email')

in both cases, only one query is run

whereas

    $emails = User::where('name', 'C1 User')->first()->pluck('email');

Will return the email of every user in the system because the result of first() is a single user model, so the query builder pluck is run on the entire database.

1 like

Please or to participate in this conversation.