laravel 方法调用的区别 $model->relation(); 和 $model->relation;
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28223289/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between method calls $model->relation(); and $model->relation;
提问by hodale
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()
我不知道这是否是最好的方法,我无法让它发挥作用。到方法的第一个列表一样,我不知道我是否需要->$beers
或->$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);
}
回答by lukasgeiter
Short answer
简答
$model->relation()
returns the relationship object
$model->relation()
返回关系对象
$model->relation
returns the resultof the relationship
$model->relation
返回关系的结果
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:
$model->relation()
可以解释得很简单。您正在调用您定义关系的实际函数。您的 fordistributor
可能看起来有点像这样:
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 Illuminate\Database\Eloquent\Relations\HasMany
所以当$store->distributors()
你打电话时,你只会得到$this->hasMany('Distributor')
它的一个实例的返回值Illuminate\Database\Eloquent\Relations\HasMany
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:
如果您想在运行之前进一步指定查询,通常会调用关系函数。例如添加一个 where 语句:
$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
.
当然,您也可以这样做:$store->distributors()->get()
但这与$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
.
Laravel 在幕后做了一些事情,允许您直接访问关系的结果作为属性。喜欢:$model->relation
。
Here's what happens in Illuminate\Database\Eloquent\Model
这是发生在 Illuminate\Database\Eloquent\Model
1)The properties don't actually exist. So if you access $store->distributors
the call will be proxied to __get()
1)这些属性实际上并不存在。因此,如果您访问$store->distributors
该呼叫将被代理到__get()
2)This method then calls getAttribute
with the property name getAttribute('distributors')
2)此方法然后getAttribute
使用属性名称调用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
)
3)在getAttribute
它检查关系是否已经加载(存在于relations
)。如果没有,并且存在关系方法,它将加载关系 ( 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()
.
4)最后 Laravel 调用getResults()
关系,然后在get()
查询构建器实例上产生 a 。(这给出了与$model->relation()->get()
.
回答by patricus
The direct answer to your question:
直接回答你的问题:
$store->distributors()
will return the actual relationship object (\Illuminate\Database\Eloquent\Relations\BelongsToMany).$store->distributors
will be a collection containing the results of the relationship query (\Illuminate\Database\Eloquent\Collection).$store->distributors()->get()
will be a collection containing the results of the relationship query (\Illuminate\Database\Eloquent\Collection).$store->distributors->get()
should return an error since you're callingget()
on a Collection object and the first parameter is not optional. If not an error, it should at least return null.
$store->distributors()
将返回实际的关系对象(\Illuminate\Database\Eloquent\Relations\BelongsToMany)。$store->distributors
将是一个包含关系查询结果的集合 (\Illuminate\Database\Eloquent\Collection)。$store->distributors()->get()
将是一个包含关系查询结果的集合 (\Illuminate\Database\Eloquent\Collection)。$store->distributors->get()
应该返回错误,因为您正在调用get()
Collection 对象并且第一个参数不是可选的。如果不是错误,它至少应该返回 null。
More information:
更多信息:
Given the following model:
给定以下模型:
class Store extends Eloquent {
public function distributors() {
return $this->belongsToMany('Distributor');
}
}
Calling the relationship method ($store->distributors()
) will return to you the relationship (\Illuminate\Database\Eloquent\Relations\BelongsToMany) object. This is basically a query object which you can continue to modify, but you still need to call some type of method to get the results (e.g. get()
, first()
, etc).
调用关系方法 ( $store->distributors()
) 将返回关系 (\Illuminate\Database\Eloquent\Relations\BelongsToMany) 对象。这基本上是一个查询对象,你可以继续修改,但你仍然需要调用一些类型的方法得到的结果(例如get()
,first()
等)。
However, accessing the relationship attribute ($store->distributors
) will return to you a collection (\Illuminate\Database\Eloquent\Collection) object containing the results from executing the relationship query.
但是,访问关系属性 ( $store->distributors
) 将返回一个集合 (\Illuminate\Database\Eloquent\Collection) 对象,其中包含执行关系查询的结果。
By default, the relationship attribute is created and assigned a value the first time it is accessed (known as "lazy loading"). So, the first time you access $store->distributors
, behind the scenes it is executing the relationship query, storing the results in the $store->distributors
attribute, and then returning those results. However, it only does this once. The next time you access $store->distributors
, the attribute already contains the data, so that is what you are accessing.
默认情况下,关系属性在第一次访问时被创建并分配一个值(称为“延迟加载”)。因此,第一次访问时$store->distributors
,它在后台执行关系查询,将结果存储在$store->distributors
属性中,然后返回这些结果。但是,它只执行一次。下次访问时$store->distributors
,该属性已包含数据,因此这就是您要访问的内容。
To illustrate this:
为了说明这一点:
// the following two statements will run the query twice
$r1 = $store->distributors()->get();
$r2 = $store->distributors()->get();
// the following two statements will run the query once.
// the first statement runs the query, populates $store->distributors, and assigns the variable
// the second statement just accesses the data now stored in $store->distributors
$r3 = $store->distributors;
$r4 = $store->distributors;
// at the end, $r1 == $r2 == $r3 == $r4
Relationships can also be "eager" loaded, using the with()
method on the query. This is done to alleviate all of the extra queries that may be needed for lazy loading (known as the n+1 problem). You can read more about that here.
也可以使用with()
查询上的方法“急切”加载关系。这样做是为了减轻延迟加载可能需要的所有额外查询(称为 n+1 问题)。您可以在此处阅读更多相关信息。
回答by Marwelln
When you work with relationships with Eloquent the property is a collection (Illuminate\Database\Eloquent\Collection
) of your relation white the method is a start of a new query.
当您使用 Eloquent 处理关系时,属性是关系的集合 ( Illuminate\Database\Eloquent\Collection
) 白色,该方法是新查询的开始。
Say your model looks like this:
假设您的模型如下所示:
class User extends Eloquent {
public function roles()
{
return $this->belongsToMany('Role');
}
}
If you try to access $user->roles
, Eloquent will run the query and fetch all roles related to that user thanks to magic methodsand returns an instance of Illuminate\Database\Eloquent\Collection
. That class has a method called get
, that's why $user->roles->get()
works for you.
如果您尝试访问$user->roles
,Eloquent 将运行查询并通过魔术方法获取与该用户相关的所有角色并返回Illuminate\Database\Eloquent\Collection
. 该类有一个名为 的方法get
,这就是为什么$user->roles->get()
对您有用。
If you try to access the method, $user->roles()
, you will instead get a query builder object so you can fine tune your query.
如果您尝试访问方法, $user->roles()
,您将获得一个查询构建器对象,以便您可以微调您的查询。
$user->roles()->whereIn('role_id', [1, 3, 4])->get();
That would only return roles where role_id
is 1
, 3
or 4
.
那只会返回角色 where role_id
is 1
, 3
or 4
。
So, the property returns a complete query and it results (Illuminate\Database\Eloquent\Collection
) while the method lets you customize your query.
因此,该属性返回一个完整的查询并产生 ( Illuminate\Database\Eloquent\Collection
),而该方法允许您自定义查询。
回答by sef8701
$distributors = $store->distributors(); Result of a method (function)
$distributors = $store->distributors(); 方法(函数)的结果
$distributors = $store->distributors; Value of a property (variable)
$distributors = $store->distributors; 属性值(变量)
$distributors = $store->distributors()->get(); Take the first one, where it's the result of a method, if the method returns an object, this is a method in that object that was returned.
$distributors = $store->distributors()->get(); 取第一个,它是方法的结果,如果该方法返回一个对象,则这是该对象中返回的一个方法。
$distributors = $store->distributors->get(); If the property is an object, then it's calling a method in that property that's an object.
$distributors = $store->distributors->get(); 如果该属性是一个对象,那么它正在调用该属性中的一个方法,该方法是一个对象。
Re ->$beers vs ->$beers() that's a dynamic name of a property/method depending on what you're for. Just making a really rough guess at what you're doing, in your class you're going to have
Re ->$beers vs ->$beers() 这是属性/方法的动态名称,具体取决于您的用途。只是对你在做什么做一个非常粗略的猜测,在你的课堂上你将会有
$this->beers = array('bud','miller','sam');
$this->beers = array('bud','miller','sam');
and in your code using the $store object, you're actually going to go something like
在你使用 $store 对象的代码中,你实际上会去类似
$drink_type = 'beers'; $drink_list = $store->$drink_type;
$drink_type = '啤酒'; $drink_list = $store->$drink_type;
And that will return $this->beers from $store, the same as writing $store->beers;
这将从 $store 返回 $this->beers,与写 $store->beers 相同;
回答by Brejk
Maybe this will be usefull.
也许这会很有用。
Access to method:
访问方法:
$object->method();
Access to property:
获得财产:
$object->property;
回答by vcanales
Imagine that the store class looks like this:
想象一下 store 类看起来像这样:
<?php
class Store {
public $distributors;
function __construct($distributors = array()) {
$this->distributors = $distributors;
}
public function distributors() {
return $this->distributors;
}
}
So the difference is:
所以区别在于:
$store = new Store(array('some guy', 'some other guy'));
$guys = $store->distributors; # accesing the $distributors property
$more = $store->distributors(); # calling the distributors() method.
回答by Duy Nguyen
The main difference is:
主要区别在于:
$distributors = $store->distributors()
return instance of the relationship object likeIlluminate\Database\Eloquent\Relations\BelongsToMany
. You can use other conditions such aswhere
after call this.$store->distributors
return instance of the collectionIlluminate/Database/Eloquent/Collection
. Laravel call the magic method__get
under the hood. It will return a result of query relationship.
$distributors = $store->distributors()
返回关系对象的实例,如Illuminate\Database\Eloquent\Relations\BelongsToMany
. 您可以使用其他条件,例如where
调用后。$store->distributors
返回集合的实例Illuminate/Database/Eloquent/Collection
。Laravel 在幕后调用魔法方法__get
。它将返回查询关系的结果。