无法让hasManyThrough工作

时间:2017-02-05 16:56:14

标签: laravel eloquent

我有三张桌子:

nCompanies (model Company)
nTransactions (model Transaction)
nBrokers (model Broker)

一家公司可能有很多交易 一个经纪人可能有很多交易

公司和经纪人没有关系。

现在我想通过公司交易获得每家公司的经纪人名单。为了做到这一点,我认为hasManyThrough()将完成这项工作。但我无法让它发挥作用。

在我的公司模型中,我有这个:

class Company extends Model
{
    protected $table = 'nCompanies';
    protected $primaryKey = 'nCompanyId';

    public function transactions()
    {
        return $this->hasMany('App\Transaction', 'nCompanyId');
    }  

    public function brokers()
    {
        //This does not work
        return $this->hasManyThrough('App\Broker', 'App\Transaction', 'nCompanyId', 'nBrokerId');  
    } 

}

以下是有效的,但我更倾向于在模型中执行此操作,以便为每个公司,公司 - >经纪人而不是单位列表获取经纪人的集合。

$companies = DB::table('nCompanies')
            ->join('nTransactions', 'nCompanies.nCompanyId', '=', 'nTransactions.nCompanyId')
            ->join('nBrokers', 'nTransactions.nBrokerId', '=', 'nBrokers.nBrokerId')
            ->selectRaw('nBrokers.*, nCompanies.*)
            ->groupBy('nCompanies.nCompanyId', 'nBrokers.nBrokerId')
            ->get();

我怎么能解决这个问题?我应该使用其他东西而不是hasManyThrough吗?

2 个答案:

答案 0 :(得分:0)

我重新阅读了您的问题,并意识到您希望通过交易获得经纪人和公司。我猜你在交易表中已经有nCompanyIdnBrokerId。然后我想应该在Transaction模型中访问经纪人,这样你就可以拥有:

class Transaction extends Model
{
    public function brokers()
    {
        return $this->hasMany('App\Broker', 'nBrokerId');  
    } 
}

所以你可以用:

来调用它
$brokers = Company::find(1)->transactions->where('id', '1')->brokers();
  

这只是我对此的看法的一个例子:

我不知道这是否有助于你得到你想要做的事情。 :)

答案 1 :(得分:0)

HasManyThrough在这里不起作用,因为Transaction和Broker之间的关系是错误的:虽然有一个HasMany关系Company-> Transaction,但只有一个HasOne关系Transaction-> Broker。对于HasManyThrough来说,两者都必须是HasMany。

建议的解决方案是在模型中使用存取器和子查询,如下所示:

public function getBrokersAttribute()
{
    $transactionIds = $this->transactions->groupBy('nBrokerId')->lists('nBrokerId');
    return Broker::find($transactionIds);
}

请注意,这会导致两个单独的查询,即使Laravel在首次加载后会缓存$transactionIds的结果。此外,此解决方案不支持急切加载,在与许多公司合作时不建议这样做。

或者,您可以使用一些循环来保持预先加载的能力:

public function getBrokersAttribute()
{
    $brokers = new Collection();
    foreach ($this->transactions as $transaction) {
        if (!$brokers->contains($transaction->broker->nBrokerId)) {
            $brokers->add($transaction->broker);
        }
    }
    return $brokers;
}

通过此示例,您可以使用->with('transactions.broker')急切加载。