SQLクエリをINでまとめるパターン

PDOを使う場合。

↓こういう関数があったとする。

    public static function getHogeFromId($id)
    {
        ...

        $sql = "SELECT `hoge` FROM some_table WHERE `id` = ?";

        $pState = $con->prepare($sql);

        $pState->execute([$id]);

        $hogeList = array();
        while ($data = $pState->fetch(PDO::FETCH_ASSOC)) {
            $hogeList[] = $data['hoge'];
        }

        return $hogeList;
    }

これがループの中で呼ばれていて、毎回DBにアクセスするので、INクエリでまとめたい。さらに、idが整数なのでPDOのbindValueを使いたい。

そういうときはこうする。

    public static function getHogeHashFromIdList($idList)
    {
        ...

        $length = count($idList);
        $placeholder = implode(',', array_fill(0, $length, '?'));

        $sql = "SELECT `id`,`hoge` FROM some_table WHERE `id`IN({$placeholder})";

        $pState = $con->prepare($sql);

        for ($i = 0; $i < $length; $i++) {
            $pState->bindValue($i + 1, $idList[$i], PDO::PARAM_INT);
        }
        $pState->execute();

        $hogeHash = array();
        while ($data = $pState->fetch(PDO::FETCH_ASSOC)) {
            $hogeHash[$data['id']] = $data['hoge'];
        }

        return $hogeHash;
    }

implode(',', array_fill(0, $length, '?'));はクエスチョンマークを指定した個数並べる。

bindValueは1から始まるらしい。

fetchとfetchAllはどうなんだろうなー。↓のRichardsって人の回答だとfetchのほうがいいみたいだけど。


$idListが空だった場合にDBにアクセスせずにそのまま空の連想配列を返すといい。

        if (!is_array($idList) || empty($idList)) {
            return array();
        }