I kept searching the web for an hour but couldn't figure this out. If we look at the eloquent relationships documentation: https://laravel.com/docs/5.2/eloquent-relationships
The example User model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Get the phone record associated with the user.
*/
public function phone()
{
return $this->hasOne('App\Phone');
}
}
Just below it, how to access the phone number of a user with id=1:
$phone = User::find(1)->phone;
Why is it phone
and not phone()
and what is the difference?
Also how does it work? If I try to call an object->name
without parenthesis in my code PHP thinks I am looking for a class variable named name
?
Some extra information:
It looks like phone is returning object(App\Models\Phone) and phone() is returning object(Illuminate\Database\Eloquent\Relations\HasOne)
If I run the code below:
User::find(1)->phone->count()
Framework executes following SQL statements:
select * from `phone` where `phone`.`user_id` = '1' and `phone`.`user_id` is not null limit 1
select count(*) as aggregate from `phone`
If I run the code below:
User::find(1)->phone()->count()
Framework executes following SQL statement:
select count(*) as aggregate from `phone` where `phone`.`user_id` = '1' and `phone`.`user_id` is not null
I don't know Laravel/Eloquent and you would need to show the find()
method for more information, but User::find(1)
returns an object so the ->phone
accesses the phone
property of that object. This has nothing to do with the find()
method that you have shown. It is shorter than this that would do the same:
$obj = User::find(1);
$phone = $obj->phone;
Do a var_dump($obj);
and you should see a phone
property. If not, then another possibility is that the class implements a __get()
magic method so that when you attempt to access the phone
property it runs the phone()
method and returns the value.
As for the first explanation, the same can be done with arrays:
function test() { return array('phone'=>'713-555-1212'); }
echo test()['phone'];
One way of thinking about it is that the public function phone()
function defines the relationship, so using $obj->phone()
would get you the Eloquent relationship itself (not the results of that relationship) which you could then modify with various query builder elements if you wanted.
Leaving out the brackets is the Eloquent shorthand for adding ->get()
or ->first()
at the end of the expression (Eloquent knows which to use based on if it's a hasOne, hasMany, etc. relationship, as defined in the function), which returns an Eloquent collection.
So, $obj->phone
is the same as $obj->phone()->first()
.