首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >不同方法调用$model->relation()和$model->relation;

不同方法调用$model->relation()和$model->relation;
EN

Stack Overflow用户
提问于 2015-01-29 19:47:28
回答 7查看 9.6K关注 0票数 46

这里有一些基本的理解/理论,我不明白这些函数调用之间的区别:

代码语言:javascript
运行
复制
$distributors = $store->distributors();
$distributors = $store->distributors;
$distributors = $store->distributors()->get();
$distributors = $store->distributors->get();

我在这里试图完成的是获得一家商店的分销商名单(很多到许多关系),他们把每个经销商的啤酒清单都列在一个巨大的列表中。

代码语言:javascript
运行
复制
foreach ($distributors as $distributor) 
{
    $available_beers = array_merge($distributor->beers(), $available_beers);
}

我不知道这是否是最好的方法,我不能让它发挥作用。类似于第一个方法列表,我不知道我是需要->$beers还是->$beers()

更新

感谢每一个回答的人!这将是我向前迈进的一个很好的参考。我最大的教训是,获取集合与获取查询生成器/关系对象之间的区别。为了将来参考那些发现这个问题的人,下面是我在我的控制器中设置的内容:

代码语言:javascript
运行
复制
$store = $this->store->find($id)->first();
$distributors = $store->distributors;
$beers = [];
foreach ($distributors as $distributor){
    $beers = array_merge($distributor->beers->lists('name', 'id'), $beers);
}
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2015-01-29 20:55:21

简短回答

$model->relation()返回关系对象

$model->relation返回关系的结果

长答案

$model->relation()可以很简单地解释。您正在调用定义关系的实际函数。您的distributor可能看起来有点像这样:

代码语言:javascript
运行
复制
public function distributors(){
    return $this->hasMany('Distributor');
}

因此,在调用$store->distributors()时,只需获得$this->hasMany('Distributor')的返回值,这是Illuminate\Database\Eloquent\Relations\HasMany的一个实例

你什么时候用它?

如果希望在运行查询之前进一步指定查询,通常会调用relationship函数。例如,添加where语句:

代码语言:javascript
运行
复制
$distributors = $store->distributors()->where('priority', '>', 4)->get();

当然,您也可以这样做:$store->distributors()->get(),但结果与$store->distributors相同。

这就引出了对动态关系属性的解释。

Laravel在引擎盖下做了一些事情,允许您作为属性直接访问关系的结果。比如:$model->relation

下面是在Illuminate\Database\Eloquent\Model中发生的事情

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

2)这个方法然后用属性名getAttribute('distributors')调用getAttribute

代码语言:javascript
运行
复制
public function __get($key)
{
    return $this->getAttribute($key);
}

3)getAttribute中检查关系是否已经加载(存在于relations中)。如果没有,并且如果存在关系方法,它将加载关系(getRelationshipFromMethod)

代码语言:javascript
运行
复制
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)最后,Laravel在关系上调用getResults(),然后在查询生成器实例上生成get()。(这提供了与$model->relation()->get()相同的结果。

票数 91
EN

Stack Overflow用户

发布于 2015-01-29 21:07:42

对你的问题的直接回答是:

  • (\Illuminate\Database\Eloquent\Relations\BelongsToMany).将返回实际的关系对象$store->distributors()
  • $store->distributors将是一个集合,包含关系查询的结果(\照明\数据库\雄辩\集合)。
  • $store->distributors()->get()将是一个集合,包含关系查询的结果(\照明\数据库\雄辩\集合)。
  • $store->distributors->get()应该返回一个错误,因为您正在对Collection对象调用get(),并且第一个参数不是可选的。如果不是错误,则至少应该返回null。

更多信息:

鉴于以下模式:

代码语言:javascript
运行
复制
class Store extends Eloquent {
    public function distributors() {
        return $this->belongsToMany('Distributor');
    }
}

调用relationship方法($store->distributors())将返回relationship (\Illuminate\Database\Eloquent\Relations\BelongsToMany)对象。这基本上是一个查询对象,您可以继续修改它,但是仍然需要调用某种类型的方法来获得结果(例如get()first()等)。

但是,访问relationship属性($store->distributors)将向您返回一个包含执行关系查询结果的集合(\照明\数据库\雄辩\ collection )对象。

默认情况下,关系属性在第一次访问时就会被创建并分配一个值(称为“延迟加载”)。因此,当您第一次访问$store->distributors时,它在幕后执行关系查询,将结果存储在$store->distributors属性中,然后返回这些结果。然而,它只做了一次。下次访问$store->distributors时,属性已经包含了数据,所以这就是您要访问的内容。

为了说明这一点:

代码语言:javascript
运行
复制
// 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

使用查询上的with()方法,还可以加载“急切”的关系。这样做是为了减轻延迟加载(称为n+1问题)可能需要的所有额外查询。您可以阅读更多关于该这里的内容。

票数 8
EN

Stack Overflow用户

发布于 2015-01-29 20:53:01

当您处理关系时,属性是关系白色的集合(Illuminate\Database\Eloquent\Collection),该方法是一个新查询的开始。

假设你的模型是这样的:

代码语言:javascript
运行
复制
class User extends Eloquent {

    public function roles()
    {
        return $this->belongsToMany('Role');
    }

}

如果您试图访问$user->roles,雄辩者将运行查询并获取与该用户相关的所有角色,这要感谢魔术法,并返回Illuminate\Database\Eloquent\Collection的一个实例。该类有一个名为get的方法,这就是为什么$user->roles->get()适用于您。

如果您尝试访问该方法,$user->roles(),您将得到一个查询生成器对象,以便您可以微调查询。

代码语言:javascript
运行
复制
$user->roles()->whereIn('role_id', [1, 3, 4])->get();

这只会返回role_id134的角色。

因此,该属性返回一个完整的查询及其结果(Illuminate\Database\Eloquent\Collection),而该方法允许您自定义查询。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28223289

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档