如何使用Yii@1.1获取带WHERE IN子句的AllBySql?

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

遗留项目使用yii@1.1。我想在CActiveRecord中创建一个查询。
原始sql中的查询为:

SELECT column
FROM table
WHERE some_id in (1, 32, 10)

而且当我直接查询数据库时,它工作得很好。我得到了所有的结果。
我在我的active record(class MyActiveRecord extends CActiveRecord)中通过下面的方法在yii中Map:

public function getColumn(array $someIds): array
    {
        $idList = rtrim(implode(', ', $someIds), ', ');
        $sql    = "SELECT column FROM table WHERE some_id IN (:idList)";

        $results = parent::model(__CLASS__)->findAllBySql(
            $sql,
            ['idList' => $idList]
        );

        return array_column($results, 'column');
    }

这段代码可以运行,但奇怪的是它只获取了第一个some_id的结果。我如何获取所有的结果?
假设我的id为1,我有5个结果,id为32,我有3个结果,id为10,我有2个结果,我期望总共有10条记录。
然而,我只得到了5个结果的id 1在yii内。我做错了什么?
(When我更改了id的顺序,始终只获取第一个id,忽略其他id。)

6ie5vjzr

6ie5vjzr1#

您的代码将创建类似SELECT column FROM table WHERE some_id IN ('1, 32, 10')的查询-您使用一个参数,并将其作为一个字符串值传递给查询。要单独传递每个ID,必须使用多个参数:

$results = parent::model(__CLASS__)->findAllBySql(
   'SELECT column FROM table WHERE some_id IN (:id1, :id2, :id3)',
    ['id1' => 1, 'id2' => 32, 'id3' => 10]
);

或者,避免使用参数并使用连接/插值,但您需要首先清理/引用值,以确保不存在SQL注入风险

$ids = implode(', ', array_map('intval', $someIds);
$results = parent::model(__CLASS__)->findAllBySql(
   "SELECT column FROM table WHERE some_id IN ($ids)"
);

但最安全、最方便的选择可能是使用CDbCommand来构建查询:

$result = Yii::app()->db->createCommand()
    ->select('column')
    ->from('table')
    ->where(['IN', 'id', $ids])
    ->queryColumn();
wxclj1h5

wxclj1h52#

我认为这是一种变通方法,但不是一种解决方案。我修改了代码,使用了CDbCriteria,但我发现它并不是最优的,因为它会获取所有字段。至少它产生了我预期的结果:

$c = new CDbCriteria();
$c->compare('some_id', $someIds);
$result = $this->findAll($c);

return array_column($result, 'column');

相关问题