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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 10:47:30  来源:igfitidea点击:

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

phparrayslaravelmethods

提问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 ->$beersor ->$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->relationreturns 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 distributorprobably 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->distributorsthe call will be proxied to __get()

1)这些属性实际上并不存在。因此,如果您访问$store->distributors该呼叫将被代理到__get()

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

2)此方法然后getAttribute使用属性名称调用getAttribute('distributors')

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

3)In getAttributeit 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->distributorswill 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 calling get()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->distributorsattribute, 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_idis 1, 3or 4.

那只会返回角色 where role_idis 1, 3or 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 like Illuminate\Database\Eloquent\Relations\BelongsToMany. You can use other conditions such as whereafter call this.

  • $store->distributorsreturn instance of the collection Illuminate/Database/Eloquent/Collection. Laravel call the magic method __getunder 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。它将返回查询关系的结果。