Yii 2活动记录有多个带有LeftJoin

mv1qrgav  于 2022-11-09  发布在  其他
关注(0)|答案(2)|浏览(157)

Yii 2的活动记录出现问题。
我想设置一个包含左连接的hasMany关系,但是在这样做时,记录中只填充了一个关系对象。
这是当前的代码--将执行的查询从Yii debug复制粘贴到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();

问题显然是加入-有没有人能启发我为什么会这样?

htzpubme

htzpubme1#

答案就在这里!
如果存在连接,则需要指定indexBy(),否则使用以下代码:
db\ActiveQuery ln 224

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

将进入removeDuplicatedModels()函数。
此函数检查modelclass参数中的主键,然后删除所有重复项。但是,由于此关系是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')
        }
        );

}
tf7tbtn2

tf7tbtn22#

请试试这个,因为这个对我很有用

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');   

}

请让我知道,如果这得到任何问题,我再说一遍,这是为我工作。

相关问题