1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「Builder」とは?SQLを即時実行せず“後から育てる”仕組み

1
Posted at

Builder(ビルダ)クラス の概要と役割を初学者向けにまとめました。

1. Builderとは何か

Builderとは「SQL(データベースへの命令文)を、PHPのコードで安全かつ簡単に組み立てるためのオブジェクト」です。

ポイントはSQLの実行タイミングです。

// ❌ 誤解:ここでデータベースからデータを取得している
$query = Project::where('work_place_id', 1);

実際には、この段階ではデータベースへの通信は1ミリ秒も発生していません
Builderは「注文書(設計図)に『WHERE work_place_id = 1』という条件を書き足しただけ」の、準備状態のオブジェクトです。

構築フェーズと実行フェーズ

注文(SQL)が確定してデータベースに送信されるのは、最後に get()paginate() などの データ取得メソッド を呼び出した瞬間だけです。

Project::query() ──> [Builder生成] (空の注文書)
     │
     ▼
->where(...)    ──> [条件追加]     (「場所の条件」を書き足す)
     │
     ▼
->orderBy(...)  ──> [並び替え追加] (「並び順の条件」を書き足す)
     │
     ▼
->paginate(10)  ──> 🔥【SQL実行】   (注文書が完成し、データベースへ送信)

データを取りに行く直前まで、「SQLを組み立て中の状態(注文書を書き換えている状態)でキープできる」 のがBuilderの最大の特徴です。

2. なぜBuilderが必要なのか(3つのメリット)

メリット①:条件に応じてSQLを後から「育てられる」

もしBuilderという仕組みがなければ、画面の入力内容(リクエスト)に応じて、生のSQL文字列を if 文でペタペタと結合しながら作らなければなりません。これは空白の入れ忘れなどによる構文エラーや、バグの温床になります。

Builderであれば、オブジェクトに対して後からメソッドを追加するだけで、安全にSQLを組み立てていくことができます。

// 1. 組み立ての開始
$query = Project::query(); 

// 2. 条件があれば、クエリを「育てる」
if (!empty($filters['skills'])) {
    $query->whereIn('skill_id', $filters['skills']); 
}

// 3. 最終的な形にして実行
$projects = $query->get();

「途中の状態を維持して持ち運べる」という性質があるからこそ、この $query を別の共通処理クラスやメソッドに引数として渡し、「別ファイルでクエリをさらに育ててもらう」 といった綺麗な設計(責務の分離)が可能になります。

メリット②:SQLインジェクションを自動で防ぐ

ユーザーが検索窓に悪意のあるプログラムを入力したとしても、Builderの where() などのメソッドを通すことで、Laravelの内部で自動的にバインド処理(無害化)が行われます。開発者が意識せずとも、安全なSQLが生成されます。

メリット③:メソッドチェーンによる可読性向上

$query->where(...)->orderBy(...)->get() のように、矢印(->)で処理を繋げて書くことができます。
これは、各メソッドが処理を終えた後に「条件を追加して新しく育った、自分自身のBuilderオブジェクト」を返却(return $this;)しているために実現しています。

3. デバッグ手法:toSql()

Builderが「本当にSQLを実行せずに、裏で設計図を作っているだけなのか」を確かめる最も有効な方法が、toSql() メソッドです。

$query = Project::query()->where('work_place_id', 1);

// 実行をストップし、組み立てられたSQLの文字列を確認する
dd($query->toSql()); 

上記を実行すると、データベースにはアクセスされず、画面に以下の文字列が出力されます。

"select * from `projects` where `work_place_id` = ?"

? の部分には、安全に処理された値(今回は 1)が後から入ります。

これを見ることで、get() を呼ぶまでは、単なる「SQLの文字列を組み立てている最中の箱」であることが一発で体感できます。

1
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?