Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
72 views
in Technique[技术] by (71.8m points)

php - Difference between method calls $model->relation(); and $model->relation;

There is some basic understanding/theory here that I am missing.I don't understand the difference between these function calls:

$distributors = $store->distributors();
$distributors = $store->distributors;
$distributors = $store->distributors()->get();
$distributors = $store->distributors->get();

What I am trying to accomplis here is to get a list of the distributors for a store (a many to many relationship), and they get each distributors list of beers into one giant list.

foreach ($distributors as $distributor) 
{
    $available_beers = array_merge($distributor->beers(), $available_beers);
}

I don't know if that is the best way to do this and I can't get it to work. Similar to the first list of methods, I don't know if I need ->$beers or ->$beers()

Update

Thanks to everyone who answered! This will be a good reference for me going forward. My biggest lesson was the difference between getting a collection back, vs getting the query builder/relationship object back. For future reference to those who find this question, here is what I set up in my controller:

$store = $this->store->find($id)->first();
$distributors = $store->distributors;
$beers = [];
foreach ($distributors as $distributor){
    $beers = array_merge($distributor->beers->lists('name', 'id'), $beers);
}
Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Short answer

$model->relation() returns the relationship object

$model->relation returns the result of the relationship


Long answer

$model->relation() can be explained pretty simple. You're calling the actual function you defined your relation with. Yours for distributor probably looks somewhat like this:

public function distributors(){
    return $this->hasMany('Distributor');
}

So when calling $store->distributors() you just get the return value of $this->hasMany('Distributor') which is an instance of IlluminateDatabaseEloquentRelationsHasMany

When do you use it?

You usually would call the relationship function if you want to further specify the query before you run it. For example add a where statement:

$distributors = $store->distributors()->where('priority', '>', 4)->get();

Of course you can also just do this: $store->distributors()->get() but that has the same result as $store->distributors.


Which brings me to the explanation of the dynamic relationship property.

Laravel does some things under the hood to allow you to directly access the results of a relationship as property. Like: $model->relation.

Here's what happens in IlluminateDatabaseEloquentModel

1) The properties don't actually exist. So if you access $store->distributors the call will be proxied to __get()

2) This method then calls getAttribute with the property name getAttribute('distributors')

public function __get($key)
{
    return $this->getAttribute($key);
}

3) In getAttribute it checks if the relationship is already loaded (exists in relations). If not and if a relationship method exists it will load the relation (getRelationshipFromMethod)

public function getAttribute($key)
{
    // code omitted for brevity

    if (array_key_exists($key, $this->relations))
    {
        return $this->relations[$key];
    }

    $camelKey = camel_case($key);

    if (method_exists($this, $camelKey))
    {
        return $this->getRelationshipFromMethod($key, $camelKey);
    }
}

4) In the end Laravel calls getResults() on the relation which then results in a get() on the query builder instance. (And that gives the same result as $model->relation()->get().


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...