概要
FuelPHP では基本的に FuelPHP が提供している Query Builder を用いて SQL を作成する
その SQL を作成する中で ORDER BY 句の設定でハマったのでメモを残す
やりたいこととしては一部の ID のみを検索上位に表示、それ以外を異なる Column で並べたいといったもの
e.g.
SELECT *
FROM `target_table`
WHERE `condition` = true
ORDER BY `target_table`.`id` = 1 DESC, `target_table`.`other_column` ASC;
環境
PHP: 8.0.30
FuelPHP: 1.8.2
MySQL: 5.7.41
結論
Query Builder の order_by()
の第一引数に条件を含めた形で DB::expr()
経由で値を渡す
$rows = DB::select()
->from('target_column')
->where('condition', '=', true)
->order_by(DB::expr('id = 1'), 'DSEC') // ← ここ
->order_by('other_column', 'ASC')
->execute()
解決策以外に試したこと
- Query Builder の
order_by()
の第二引数に直接値を入れる$rows = DB::select() ->from('target_column') ->where('condition', '=', true) ->order_by('id', 1) // 対象の条件 ->order_by('other_column', 'ASC') ->execute()
- Query Buildr の
order_by()
の第二引数に条件込の文字列を渡す$rows = DB::select() ->from('target_column') ->where('condition', '=', true) ->order_by('id', '= 1 DESC') // 対象の条件 ->order_by('other_column', 'ASC') ->execute()
- Query Builder の
order_by()
の第二引数にDB::expr()
を用いて条件を渡す$rows = DB::select() ->from('target_column') ->where('condition', '=', true) ->order_by('id', DB::expr(' = 1 DESC')) // 対象の条件 ->order_by('other_column', 'ASC') ->execute()
実際のコードの確認
どれもうまく動かなかったので execute()
の代わりに compile()
を呼びログを確認したところ id DESC
となっていた
そのため実際の Query Builder のコードを確認すると ASC
以外は全て DESC
となるようになっていた
fuel/core/classes/database/query.php#198
$direction = strtoupper($direction);
if ( ! empty($direction))
{
$direction = ' '.($direction == 'ASC' ? 'ASC' : 'DESC');
}
そのため値の方ではなく Column の方を置き換える形で試したところうまく動作した
まとめ
- FuelPHP の Query Builder で ORDER BY 句の条件をつける場合は第一引数に
DB::expr()
を用いて条件指定を行う - 簡単に試して動かない場合はライブラリのコードを読んだ方が早い