tabimoba.net

とあるエンジニアの雑記帳

FuelPHPのQuery Builderでjoinした表のカラム名の重複をうまく解決する方法

Fuelphpで結合表(joinした表)から値を取得する際にORマッパーを用いると重複するカラム名があってもよしなに処理してくれるのですが、Query Builderの場合は一方のテーブルのカラムの値しか出力されないため、重複するカラム名に対してエイリアスを付加する必要があります。

しかし、カラム名やエイリアスを1つ1つ手で指定するのは非常に面倒で保守性も良くないため、今回はDB::list_columns関数でテーブルのカラム名を取得して、それをもとにエイリアスを作成して対応することにしました。

カラム名とエイリアスを出力するコードの例

$cols = array(
    'users' => DB::list_columns('users'),
    'user_infos' => DB::list_columns('user_infos')
);

foreach ($cols as $tbl => $col) {
    foreach ($col as $val) {
        $cols_name[$tbl . '.' . $val['name']] = array($tbl . '.' . $val['name'], $tbl . '_' . $val['name']);
    }

}

必要のないカラム名は、foreachの中にswitch文で条件分岐させて取り除くか、foreach前あるいは後にunset関数で除けば良いでしょう。

上記コードより取得したカラム名をもとにselectする方法は以下の通りとなります。 通常は素直に例1の方法を用いれば良いと思います。 (FuelPHPにはDB::select_array関数があるので、例2のようにcall_user_func_array関数で頑張って配列を引数化する必要はありませんが、まあこんな方法もあるよということで)

使用例

例1:DB::select_array関数で配列の値を引数として用いる

public static function get_user_list() {
    $cols = array(
        'users' => DB::list_columns('users'),
        'user_infos' => DB::list_columns('user_infos')
    );

    foreach ($cols as $tbl => $col) {
        foreach ($col as $val) {
            $cols_name[] = array($tbl . '.' . $val['name'], $tbl . '_' . $val['name']);
        }

    }

    $query = call_user_func_array('DB::select',$cols_name);
    $query->from('users');
    $query->join('user_infos','LEFT');
    $query->on('users.id','=','user_infos.id');
    $result = $query->execute()->as_array();
    return $result;
}

例2:call_user_func_array関数で配列の値を引数として用いる

public static function get_user_list() {
    $cols = array(
        'users' => DB::list_columns('users'),
        'user_infos' => DB::list_columns('user_infos')
    );

    foreach ($cols as $tbl => $col) {
        foreach ($col as $val) {
            $cols_name[] = array($tbl . '.' . $val['name'], $tbl . '_' . $val['name']);
        }

    }

    $query = call_user_func_array('DB::select',$cols_name);
    $query->from('users');
    $query->join('user_infos','LEFT');
    $query->on('users.id','=','user_infos.id');
    $result = $query->execute()->as_array();
    return $result;
}