LoginSignup
0
0

More than 1 year has passed since last update.

toSql() のクエリの ? に対するバインドが失敗しているとかいうバグ

Posted at

はじめに

未経験でエンジニアになって間もないので、知識不足などあると思います。
何卒ご理解ください。

前提条件

たくさんの会合があって、それぞれに参加者がいる状況を想定して開発しています。
会合情報が書いてあるテーブル(ここではMeetingsテーブルとします)

参加者情報が書いてあるテーブル(ここではParticipantsテーブルとします)
があって
それぞれ MeetingsテーブルのidParticipantsテーブルのmeeting_id で結合している。

Participantsの情報の中に、status= 0:参加、1:不参加 という情報があり、
参加数だけ取ってきて表示したいとします。

$sub = Participant::select('participants.meeting_id',DB::raw('count(*) as cnt'))
                    ->where('participants.status', '=', 0)
                    ->groupby('patricipants.meeting_id');

$query = Meeting::select(
            'meetings.id as id',
            'meetings.name as name',
           その他Meetingの情報
            'entry_num.cnt'
        )
            ->leftjoin(DB::raw('('.$sub->toSql().') as entry_num'),'meetings.id','entry_num.meeting_id');

としたところ、下記のエラーが・・・

SQLSTATE[HY000]: General error: 2031 No data supplied for parameters in prepared statement

select
  count(*) as aggregate
from
  `meetings`
  left join (
    select
      `participants`.`meeting_id`,
      count(*) as cnt
    from
      `participants`
    where
      `participants`.`status` = ?
    group by
      `participants`.`meeting_id`
  ) as entry_num on `meetings`.`id` = `entry_num`.`meeting_id`

ナンノコッチャわからない・・・
where
participants.status = ?
ってstatus=0って指定しているはずだけどな??

とりあえず片っ端からググる

toSql()ってなんだろうなと思ってググっていると
こちらの記事に出会いました。
https://codelikes.com/confirm-laravel-sql/#toc2

toSqlメソッドを呼ぶと、実際に実行するSQLがパラメータ箇所を「?」で伏せた状態で返ってきます。

なるほど、だから status = 0 が取れていなかったのか・・・

$sub = Participant::select('participants.meeting_id',DB::raw('count(*) as cnt'))
                    ->where('participants.status', '=', 0)
                    ->groupby('patricipants.meeting_id');

$subGetBindings = $subGetBindings = preg_replace_array('/\?/', $sub->getBindings(), $sub->toSql());

$query = Meeting::select(
            'meetings.id as id',
            'meetings.name as name',
           その他Meetingの情報
            'entry_num.cnt'
        )
            ->leftjoin(DB::raw('('.$subGetBindings.') as entry_num'),'meetings.id','entry_num.meeting_id');

$subGetBindings = $subGetBindings = preg_replace_array('/\?/', $sub->getBindings(), $sub->toSql());
ここでLaravelで用意されているpreg_replace_arrayヘルパーを使用して置換することができます。

すると、キャンセル分を含めずに参加人数を取ってくることができました:point_up:

忘れないようにメモとして残しておきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0