Yii 2活动记录有很多与LeftJoin

时间:2015-10-26 21:56:44

标签: php mysql activerecord yii

在Yii2的Active Record上遇到麻烦。

我想设置一个包含左连接的hasMany关系,但是这样做时,记录只填充一个关系对象。

这是当前的代码 - 将执行的查询从Yii调试复制到navicat肯定会返回多个结果。

public function getx()
{

    return $this->hasMany(x::className(),['x' => 'x'])
        ->viaTable('a', ['arId' => 'arId'], function ($query){


            $query->leftJoin('a b', 'a.type = b.type AND a.val < b.val')
                ->andWhere('a.foo IN (0,1,2,3)')
                ->andWhere('a.bar IN ((0,1,2,3)')
                ->andWhere('a.moo IN ((0,1,2,3)')
                ->andWhere('b.val IS NULL');
        }
        );

}

以下代码可以正常工作(当然查询不同)。

    return $this->hasMany(x::className(),['x' => 'x'])
        ->viaTable('a', ['arId' => 'arId'], function ($query){

            $query->andWhere(['and', ['foo' => [0,1,2,3]],
                    ['bar' => [0,1,2,3]],
                    ['moo' => [0,1,2,3]],
                ]
                );
            }
        );

它在控制器中被调用,具有以下内容:

$rs = ar::find(1)->with('x')->all();

问题显然是加入 - 任何人都可以告诉我为什么会这样吗?

2 个答案:

答案 0 :(得分:0)

请尝试一下,因为这对我有用

public function getx()
{

    return $this->hasMany(x::className(), ['xId' => 'xId'])
                         ->leftJoin('a b', 'a.type = b.type AND a.val < b.val', 
                        function($query){
                            '..here you can add more join'
                        })
                        ->andWhere('a.foo IN (0,1,2,3)')
                ->andWhere('a.bar IN ((0,1,2,3)')
                ->andWhere('a.moo IN ((0,1,2,3)')
                ->andWhere('b.val IS NULL');   

}

请告诉我这是否有问题,因为我再次说它对我有用。

答案 1 :(得分:-1)

所以这就是答案!

如果有连接,则需要另外指定indexBy()以下代码:

db\ActiveQuery ln 224

    if (!empty($this->join) && $this->indexBy === null) {
        $models = $this->removeDuplicatedModels($models);
    }

会将您转到removeDuplicatedModels()功能。

此函数检查modelclass参数中的主键,然后删除所有重复项。然而,联结表期待多个原色(来自父Active Record),因为它是hasMany()关系。因此,您需要通过将indexBy参数设置为所需的主键来覆盖此检查。

以下代码适用:

public function getx()
{

    return $this->hasMany(x::className(),['xId' => 'xId'])
        ->viaTable('a', ['arId' => 'arId'], function ($query){
            $query->leftJoin('a b', 'a.type = b.type AND a.val < b.val')
                ->andWhere('a.foo IN (0,1,2,3)')
                ->andWhere('a.bar IN ((0,1,2,3)')
                ->andWhere('a.moo IN ((0,1,2,3)')
                ->andWhere('b.val IS NULL')
                ->indexBy('xId')
        }
        );

}