Laravel+PostgreSQLでの異なる型のINNER JOINの方法
2019/10/122017/09/26投稿ではてなブログから移行した内容です.
データベースクエリビルダ
Laravelは、データベースクエリビルダってのがある。
データベースクエリビルダはスラスラと書ける(fluent)便利なインターフェイスで、 クエリを作成し実行するために使用します。 アプリケーションで行われるほとんどのデータベース操作が可能で、 サポートしている全データベースシステムに対し使用できます。
こいつのおかげでSQL文を書かなくて済む。
SELECT文とかもこんな感じで書ける。
$users = DB::table('users')->select('name', 'email as user_email')->get();
今回問題のINNER JOIN文もこんな感じでかける。
$users = DB::table('users')
->join('contacts', 'users.id', '=', 'contacts.user_id')
->join('orders', 'users.id', '=', 'orders.user_id')
->select('users.*', 'contacts.phone', 'orders.price')
->get();
違う型でのINNER JOINする方法
今回ぶち当たった壁は違う型でのINNER JOINする方法。
上記の例の場合、usersテーブルのidがint8・contactsテーブルのuser_idがvarcharの場合、
型が違うためjoinできない。
CASTすればよいと思い、試してみた。
$users = DB::table('users')
->join('contacts', 'users.id', '=', 'contacts.user_id::int')
->get();
contacts.user_id::intなんて存在しないよって怒られる。
原因は多分これみたい。
LaravelクエリビルダはアプリケーションをSQLインジェクション攻撃から守るために、 PDOパラメーターによるバインディングを使用します。 バインドする文字列をクリーンしてから渡す必要はありません。
解決方法はDB::raw()メソッド
たまにクエリの中でSQLを直接使用したいことがあります。 このようなSQLでは文字をそのまま埋め込むだけですので、 SQLインジェクションをされないように気をつけてください! エスケープなしのSQLを使用する場合はDB::rawメソッドを使用します。
こんな感じにすれば完了
$users = DB::table('users')
->join('contacts', 'users.id', '=', DB::raw('contacts.user_id::int'))
->get();
参考サイト
Twitterフォロー待ってます!