首页 > 解决方案 > 如何使用 Yii@1.1 获取带有 WHERE IN 子句的 fetchAllBySql?

问题描述

一个遗留项目使用 yii@1.1。我想在CActiveRecord.

原始 sql 中的查询将是:

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

当我直接查询数据库时它工作正常。我得到所有的结果。

class MyActiveRecord extends CActiveRecord我通过 yii 中的以下方法将其映射到我的活动记录 ( ) 中:

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

该代码有效,但奇怪的是它只获取了 first 的结果some_id。我如何获取所有这些?

假设我的 id 1 有 5 个结果,32 有 3 个结果,10 有 2 个结果,我预计总共有 10 条记录。

然而,我只取回 yii 中 id 1 的 5 个结果。我究竟做错了什么?

(当我更改 id 的顺序时,总是只会获取第一个 id,其他的会被忽略。)

标签: phpsqlyiiwhere-inyii1.x

解决方案


您的代码将创建类似查询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();

推荐阅读