【Laravel】クエリビルダによるデータベース操作:使用方法とメソッド一覧

2023.11.12 /

【Laravel】クエリビルダによるデータベース操作:使用方法とメソッド一覧

記事ではLaravelにおける、DBファサードクエリビルダによるデータベース操作について詳しく解説していきます。ここでは詳しいクエリビルダの使用方法や利用できるメソッド一覧も確認できます。

Laravelでデータベース操作をする方法の一つにDBファサードでクエリビルダを使用する方法があります。

DBファサードのDBクラスには「クエリビルダ」という機能が備わっており、様々なメソッドをメソッドチェーンとして連続して呼び出してSQLクエリ文を生成することができます。

クエリビルダはLaravelのデータベース操作では必須の知識です。本記事を通して、DBファサードのクエリビルダについて理解を深めてください。

Laravel:データベース操作をする方法

Laravelでデータベース操作をする方法として以下3つが主要な方法です。

Laravelでデータベース操作をする方法
  • DBファサード(SQLクエリ)
  • DBファサード(クエリビルダ)
  • Eloquent(エロクアント)

本記事ではDBファサードのクエリビルダについて解説していきます。

ファサード(Facades)とは

ファサードとはクラスをインスタンス化しなくてもメソッドを実行できる機能です。

よく利用されるファサードとしてルーティングのweb.phpではRouteファサード、データベース操作で利用するDBファサード、Authファサードなどがあります。

これらのファサードはconfig/app.phpのaliasesで定義されています。

データベース操作をする場合、Eloquentまたはクエリビルダのどちらかを利用することが多いです。ではこれらはどのような使い分けをするのでしょうか。

Eloquent ではモデルを利用することでデータベース操作が容易になり、コードの読み書きが簡単になります。便利なEloquentですが次のようなデメリットがあります。

Eloquentのデメリット
  • 実行されるSQLがわかりづらい、SQLのカスタマイズが難しい
  • 結合するとモデルとテーブルの関係性が壊れる
  • 件数が増えると遅くなる

レコード件数が多い場合や、複数のテーブルを結合する操作ではEloquentの利用はふさわしくないです。このような場面ではDBファサードからクエリビルダを利用することが望ましいです。

またSQLをそのまま実行してデータベース操作をしたい場合はDBファサード(SQLクエリ)を利用してください。DBファサード(SQLクエリ)について詳しくは以下記事をご参照ください。

クエリビルダとは

DBファサードのDBクラスには「クエリビルダ」という機能が備わっています。クエリビルダとは様々なメソッドをメソッドチェーンとして連続して呼び出してSQLクエリ文を生成する機能です。Laravelでデータベース操作をする際には必須の知識です。

DBファサードとは

DBファサードとはデータベース操作に必要な機能をまとめたクラスのファサードです。Illuminate\Support\Facadesに用意されているファサードであり、クラス名は「DB」です。

DBクラスは以下構文に沿って利用します。

構文

$変数 = DB::メソッド

メソッドを呼び出してSQLクエリ文を作成していくため、そこまでSQLを意識せずに利用できます。また用意されているメソッドには発行されるSQLを連想しやすい名前が付けられています。

Eloquentとは異なりモデルオブジェクトに依存しません。書き方もSQLを書くように記述でき、カスタマイズが容易です。

またクエリビルダではPDOパラメーターバインディングを使用しており、SQLインジェクション攻撃を防ぐ役割も果たします。

注意点

クエリビルダの戻り値はコレクションです

クエリビルダの使用方法

DBファサードをuseする

DBファサードを利用する場合、必ずスクリプトにDBファサードをuse文で読み込んでおきます。

use Illuminate\Support\Facades\DB;

基本的なクエリビルダの使い方

クエリビルダは以下のように、DB:table(テーブル名)で始まり、そのあとはメソッドチェーンを連続して呼び出して必要なSQLクエリを作成します。

$blogs = DB::table('blogs')
    ->where('title', 'Laravel')
    ->orderBy('contents', 'asc')
    ->get();

最後はget()やfind()、value()といったメソッドを使用してクエリ結果を取得します。

POINT

データベースに対する処理はgetメソッドやfirstメソッドなどが呼ばれるまでは実行されません

クエリビルダのメソッド一覧

ビルダの取得:table()

クエリビルダを利用する場合、まず最初にDBクラスのtable()メソッドを呼び出します。tableメソッドにより「ビルダ」を取得し、その後はビルダに備わっているメソッドを呼び出していく(メソッドチェーン)ことで、SQLクエリ文が生成されます。

構文

$変数 = DB::table(テーブル名);

ビルダはIlluminate\Database\QueryにあるBilderクラスです。

レコードの取得:get()

クエリビルダの最後にはレコードを取得するメソッドを使用します。レコードを取得するメソッドの一つにget()メソッドがあります。

get()メソッドはクエリの結果からレコードを取得するメソッドであり、SQLのselect文に相当します。そのためクエリ結果のすべてのレコードを返します。get()メソッドの戻り値はコレクションとなっています。

public function index()
{
    $blogs = DB::table('blogs')->get();
    return view('user.index', ['blogs' => $blogs]);
}

get()メソッドの引数にフィールドを指定することで、指定したフィールドだけを取り出すことができます。引数なしで利用するとすべてのフィールドの値を取得します。

$blogs = DB::table('blogs')->get('title', 'contents'));

最初のレコードを取得:first()

クエリ結果から最初のレコードのみを取得するにはfirst()メソッドを使用します。返すレコードは1つのみなので、戻り値はそのレコードのオブジェクトとなります。

first()メソッドはwhere()メソッドなどと共に利用され、クエリ結果が1つのレコードのみであることがわかっている場合に利用されることが多いです。

$blog = DB::table('blogs')->where('title', 'Laravel')->first();

return $blog->contents;

単一のフィールド値のみ取得:value()

クエリ結果から単一のフィールド値のみ取得するにはvalue()メソッドを使用します。value()の引数には取得したいフィールドを指定します。

$contents = DB::table('blogs')->where('title', 'Laravel')->value('contents');

idから単一のレコードを取得:find()

指定したidと一致する単一のレコードを取得するにはfind()メソッドを使用します。引数にidを指定することで、idと一致するレコードが返されます。

$blog = DB::table('blogs')->find(54);

指定したカラムの取得:select()

select()メソッドは指定したカラムの値を取得するメソッドです。SQLのselectに相当します。

構文

select(フィールド1, フィールド2, …)

引数には取得したいカラム(フィールド名)を指定します。クエリビルダでselect()メソッドを使用しない場合はデフォルトですべてのカラムが取得されるselect('*')が使用されていることとなります。

select()メソッドだけではクエリは実行されません。get()などをメソッドチェーンすることでクエリ結果を取得できます。

$users = DB::table('users')->select('name', 'age')->get();

集計関数を使用する場合はselectの引数には次のように指定します。

$orders = DB::table('orders')
    ->select('group_id', DB::raw('count(*) as total_orders'))
    ->groupBy('group_id')
    ->get();

カラムの値をすべて取得:pluck()

特定のカラム(フィールド)の値をすべて取得するにはpluck()メソッドを使用します。

構文

pluck(フィールド名);

引数には取得したいフィールド名を指定し、指定したフィールドの値をコレクションとして返します。返された値は以下のようにforeachで処理することもできます。

$users = DB::table('users')->pluck('name');
foreach ($users as $user) {
    echo $user;
}

コレクションではなく配列で利用したい場合はpluck()の後にall()を使用して配列に変換しましょう。

$users = DB::table('users')->pluck('name')->all();

条件指定:where()

SQLのwhere句に相当するメソッドがwhere()メソッドです。引数に条件を指定することでレコードの条件検索ができます。

引数にフィールド名と値の2つを指定することでフィールド名が値と合致するレコードに絞り込みます。

構文

where(フィールド名, 値)

$blog = DB::table('blogs')->where('title', 'Laravel')->first();

引数にフィールド名と演算記号、値の3つを指定することでより細かい検索ができます。例えばidが54より大きいレコードを検索するなどが可能となります。

構文

where(フィールド名, 演算記号, 値);

$blog = DB::table('blogs')->where('id', '>', 54)->get();

複数の条件指定:orWhere()

複数の条件を指定するにはwhere()メソッドとorWhere()メソッドを組み合わせて使用します。

すべての条件に合致するレコードのみを検索する場合はwhere()のみを以下構文のように複数続けて使用します。

構文

where(条件1)->where(条件2)

上記では条件1と条件2の2つに合致するレコードが取得できます。

条件に1つでも合致するレコードすべてを検索する場合はwhere()メソッドとorWhere()メソッドを使用します。

構文

where(条件1)->orWhere(条件2)

上記では条件1または条件2のどちらかに合致するレコードが取得できます。例えばユーザーから送信されたテキストがtitleまたはcontentsフィールドに含まれるレコードを抽出するには次のように記述します。

public function search(Request $request)
{
    $text = $request->text;
    $items = DB::table('blogs')
        ->where('title', 'like', '%' . $text . '%')
        ->orWhere('contents', 'like', '%' . $text . '%')
        ->get();
    return view('search', ['items' => $items]);
}

検索の条件を文字列で指定:whereRaw/orWhereRaw()

検索条件を文字列で指定したい場合はwhereRaw()メソッドまたはorWhereRaw()を使用します。

構文

whereRaw(条件式, 配列);

第一引数には検索条件を式で指定、第二引数には条件式内の「?」またはプレースホルダに埋め込むパラメータを配列(連想配列)で指定します。

public function search(Request $request)
{
    $items = DB::table('users')
        ->whereRaw('age >= ? and age <= ? ', [20, 54])
        ->get();
    return view('search', ['items' => $items]);
}

以下コード例ではブログを作成した本人のブログまたは管理者権限のユーザーであればすべてのブログがビューに返される内容となっています。

public function search(Request $request)
{
    $items = DB::table('blogs')
        ->where('created_by', \Auth::user()->id)
        ->orWhereRaw('1=?', [$request->user()->is_admin?1:0])
        ->get();
    return view('search', ['items' => $items]);
}

並び順の指定:orderBy()

クエリ文で取り出されるレコードの並び順を指定するにはorderBy()メソッドを使用します。第一引数にはフィールド名、第二引数には昇順を表す「asc」、または降順を表す「desc」を指定します。

構文

orderBy(フィールド名, ascまたはdesc)

$blog = DB::table('blogs')->where('title', 'Laravel')->orderBy('contents', 'asc')->get();

カラムの値でグループ化:groupBy

groupBy()メソッドはクエリ結果を特定のカラム(フィールド)の値に基づいてグループ化するメソッドです。SQLのgroup byに相当します。

構文

groupBy(フィールド名)

例えばユーザーの住んでいる都道府県でグループ化や商品の品目でグループ化するといった使い方をされます。

グループ化した項目の合計値やカウントを計測するために、groupBy()メソッドは集計関数(sum()やcount()、max()など)と共に利用されることが多いです。

以下コード例はgroup_idでグループ化して、そのレコード数をカウントしています。

$counts = DB::table('users')
    ->select('group_id', DB::raw('count(*) as total'))
    ->groupBy('group_id')
    ->get();

グループ化した結果を条件抽出:having/havingRaw

having()メソッドはグループ化した結果をフィルタリング(抽出条件を指定)するメソッドです。SQLのhavingに相当します。主にgroupBy()メソッドと組み合わせて利用します。

構文

having(フィールド名, 演算子, 比較する値)

where()メソッドはグループ化する前の個々のレコードに対して条件検索をしますが、having()メソッドの対象はグループ化されたデータです。

例えば購入金額の平均がいくら以上の顧客を抽出するなどで利用されます。以下にコード例を記します。

$users = DB::table('users')
    ->groupBy('group_id')
    ->having('group_id', '>', 54)
    ->get();

生のSQLを引数で使用したい場合はhavingRaw()メソッドを使用します。

構文

havingRaw(条件式, 配列);

第一引数には検索条件を式で指定、第二引数には条件式内の「?」またはプレースホルダに埋め込むパラメータを配列(連想配列)で指定します。

$results = DB::table('orders')
    ->groupBy('account_id')
    ->havingRaw('SUM(amount) > ?', [5400])
    ->get();

抽出するレコードの制限:limit()

クエリ結果から抽出するレコード数を制限したい場合はlimit()メソッドを使用します。limit()メソッドは引数に指定した数だけレコードを取得します。

構文

limit(数値)

指定した位置からレコードを取得:offset()

クエリ結果から指定した位置以降のレコードを抽出するにはoffset()メソッドを使用します。offset()の引数に指定した数値からのレコードを取得します。

構文

offset(数値)

レコードの追加:insert()

クエリビルダによるレコードを追加するにはinsert()メソッドを使用します。

構文

insert(配列);

引数にはカラム名と値の配列を渡します。つまり連想配列のような形になります。これにより配列のデータがレコードとして保存されます。

DB::table('users')->insert([
    'email' => 'office54@office54.net',
    'age' => 54
]);

レコードの更新:update()

クエリビルダによる既存のレコードの更新にはupdate()メソッドを使用します。

構文

update(配列);

insert()と同様に引数にはカラム名と値の配列を渡します。update()によるレコードの更新を行う場合は、where()メソッドなどを用いてレコードを絞り込んでから更新を行います。

注意点

where()メソッドなどでレコードを絞り込まずに使用すると、すべてのレコードを更新してしまう恐れがあります

DB::table('users')
    ->where('id', 55)
    ->update([
        'email' => 'office54@office54.net',
        'age' => 55
]);

レコードの削除:delete()

クエリビルダによる既存レコードの削除にはdelete()メソッドを使用します。

構文

delete();

引数には何も指定せず、呼び出すだけでレコードを削除できます。delete()メソッドを使用する場合も必ずwhere()メソッドなどでレコードを絞り込んでおく必要があります。

注意点

where()メソッドなどでレコードを絞り込まないでdelete()を使用すると、すべてのレコードが削除される可能性があります

DB::table('users')
    ->where('id', 1)
    ->delete();