はじめに
Laravelが提供しているEloquentというORMは非常に便利で、複雑なクエリも簡単に作成できます。便利なのですが、残念ながらEloquentが使えない場合もあります。
たとえば、クエリのコストや負荷を計測するためのexplain
を実行したい場合です。
もう一つは、弊社では安全のために本番のtinkerでコマンドを実行しないルール
があり、データ抽出の依頼があった場合にはDBのレプリカで生のSQLを実行することになっています。
そのような場合、Eloquentから生のSQLに変換するためにdd()
やtoSql()
といった関数もありましたが、出力されるSQLにクエリパラメータがバインドされず、?
というプレースホルダのままになってしまいました。そのため、手動でクエリパラメータをSQL文に置き換える必要がありました。
Laravel 10.15のリリースでは、toRawSql()
関数が追加され、バインドされた値が含まれたSQL文を出力できるようになりました。
toSql()・dd()・toRawSql()比較
今まであったdd()・toSql()
実行したいselectクエリーの最後にget()
の代わりにdd()
もしくはtoSql()
を使用すると、SQL文を出力することができます。
dd()
の機能はSQL文だけでなく、クエリパラメーターの配列も一緒に出力されます。
User::where('created_at', '>', '2023-01-01 00:00:00')->dd();
// "SELECT * FROM users WHERE created_at > ?"
// array [
// "2023-01-01 00:00:00"
// ]
toSql()
の場合、SQL文のみが出力されます。クエリパラメータを出力したい場合には、以下のようにクエリビルダーを変数に代入してからgetBindings()
を実行すると、パラメータの配列が出力されます!
$query = User::where('created_at', '>', '2023-01-01 00:00:00'); // クエリビルダを代入
$query->toSql(); // toSql()を実行しSQL分を出力
// "SELECT * FROM users WHERE created_at > ?"
$query->getBindings(); // パラメーターの配列を出力
// [
// "2023-01-01 00:00:00",
// ]
確かに、両方は非常に便利な機能ですが、生のSQLを実行する前に、SQL文内の?
を手動でコピーペーストで置き換える必要があるため、時間がかかる上にミスの可能性もあります。
新しく追加されたtoRawSql()
dd()
やtoSql()
と同じような使い方でバインド値が組み込まれたSQL文が出力できます。
User::where('created_at', '>', '2023-01-01 00:00:00')->toRawSql();
// "SELECT * FROM users WHERE created_at > '2023-01-01 00:00:00'"
ご覧のように、出力されたクエリをそのままコピーペーストし、直ぐにSQLのサーバー(弊社の場合、本番のレプリカ)ですぐに実行することができます!非常に便利な機能ですね!
まとめ
toRawSql()
の機能により、Eloquentのクエリをパラメータが含まれたSQL文として出力することができるようになりました。これにより、コピーペーストの手間やミスが減り、非常に便利な機能となっています。
SQLに苦手意識のある方や、Eloquentが実行したクエリの内容やコストを確認したい方はぜひお試しください!