エンジニ屋.com(エンジニヤドットコム)

分かりやすくを意識して情報発信!

【Laravel】Eloquent・クエリビルダ・生SQLの違いをしっかり理解【比較】

Laravelを使ってデータベースからデータを取得するとき、Eloquent ORM、クエリビルダ、生のSQLの3つの方法があります。

この記事ではそれぞれの違いを詳しく見ていきます!!

先ずは、説明の為にサンプル用として、usersテーブルを用意しています。

下のようにデータを格納して準備をしました。

<usersテーブル>

id name email ....
1 もりし enginiya@example.com ....
2 たなか tanaka@example.com ....

1. Eloquent ORM

EloquentはORM(Object-Relational Mapping)の一種で、Laravelが提供するデータベース操作のための実装方法です。

つまり、EloquentはORMツールの一つであり、ORM自体はソフトウェアの設計パターンの一つを指します。

ORMとは、オブジェクト指向プログラミング言語とリレーショナルデータベースの間の「架け橋」のようなものです。

オブジェクト指向の概念を用いてデータベースからデータを取り出し、そのデータをプログラム内のオブジェクトとして操作できるようにします。

この結果、SQLクエリを直接書くことなく、データベースとやり取りすることができます。

Laravelでデータベース操作を行うための主要な手段となっています。

例えば、ModelディレクトリにUser.phpを作成していたとします。

すべてのユーザー情報を取得するには、以下のようなコードを書くだけでデータを取得できます。

$users = App\Models\User::all();

返却値をdd()関数で確認します。

$users = App\Models\User::all();
dd($users);

結果:

返却値の解説:

Illuminate\Database\Eloquent\Collectionオブジェクトとして返されます。

Eloquent Collectionのメソッドには、load (リレーションシップの遅延読み込み)やcontains (コレクション内のモデルの存在チェック)などがあり使うことができます。

また、Eloquent CollectionはCollectionクラスを継承しており、基本的なCollectionが持つすべてのメソッドを使用できます。

さらに、データベースの各行に対応したオブジェクトで格納されているので、Eloquentの強力な機能、例えばアクセサやミューテータ、リレーションシップなどを活用することができます。

これらの機能により、より直感的で効率的なデータ操作が可能になります。

主なメリット:

・モデルクラスを通じてデータベース操作を行うため、直感的でオブジェクト指向的な操作が可能です。

・モデル間のリレーションシップを簡単に表現でき、関連するデータの取得が容易になります。

・モデルイベントやアクセサ、ミューテータ等、データの操作や取得に細かな制御を行うための豊富な機能が用意されています。

・クエリビルダの全機能を内包しています。

2. クエリビルダ

クエリビルダも直感的にSQLクエリ(データベースへの質問)を作れるツールです。

クエリビルダは、より複雑なクエリを柔軟に作成することができます。

後程詳しく見ていきますが、Eloquentはクエリビルダの全機能を内包しているので、クエリビルダはEloquentと併せて使用することが多いです。

クエリビルダのみを使用して、すべてのユーザー情報を取得するには、以下のようなコードを書きます。

$users = DB::table('users')->get();

返却値をdd()関数で確認します。

$users = DB::table('users')->get();
dd($users);

結果:

返却値の解説:

Illuminate\Support\Collectionオブジェクトとして返されます。

このCollectionの各要素は、stdClassオブジェクトです。

このstdClassオブジェクトは単なるデータコンテナで、特定のメソッドを持たないため、Eloquentのようなビジネスロジックの組み込みはできません。

しかし、便利なCollectionメソッドを利用できるため、集計やデータ変換などが容易に行えます。

主なメリット:

・SQLのような記述を行いながら、メソッド呼び出しが連鎖的に(チェーン状に)を使ってコードを書くため、コードの可読性を高めることができます。

・Eloquentモデルを定義しなくても使用でき、テーブルに対して直接クエリを記述することが可能です。

・クエリの記述が柔軟で、複雑なクエリも比較的簡単に書くことができます。

3. 生のSQL

生のSQLは、直接SQL言語でデータベースとやりとりする方法です。

これは一部の複雑な操作や特殊なケースで必要となる場合があります。

例えば、すべてのユーザー情報を取得するには、以下のようなコードを書きます。

$users = DB::select('select * from users');

こちらもdd()関数で確認します。

$users = DB::select('select * from users');
dd($users);

返却値の解説:

配列として返されます。

この配列の各要素は、stdClassオブジェクトです。

こちらもstdClassオブジェクトとしてデータが返されますが、Collectionオブジェクトと違い、Collectionメソッドを利用することはできません。

生のSQLは最も直接的なデータアクセス方法ですが、その分操作や変換は手動で行う必要があります。

生のSQLを使うメリットは、主に以下です:

・LaravelのクエリビルダやEloquent ORMがカバーできない特殊なSQLクエリを直接書くことが可能です。

例えば、MySQLの固有の関数を使用する場合は、生のSQLを使用します。

以下は、DATEDIFF関数を使用して、特定の日付と今日の日付の差を計算するクエリです。

$result = DB::select('SELECT DATEDIFF(NOW(), created_at) AS days FROM users WHERE id = 1');

・シンプルな操作や最適化されたクエリをデータベースに送る場合に便利です。

ただし、生のSQLを書く場合はSQLインジェクションなどのセキュリティ問題を適切に対処する必要があります。

Eloquent のクエリビルダ

Eloquentでのメリットで「クエリビルダの全機能を内包しています。」と述べたように

内部でクエリビルダを利用しており、そのため、Eloquentモデルを通じてクエリビルダのwhere()のようなメソッドを呼び出すことが可能です。

では、Eloquentとクエリビルダでwhere()を使った場合、どのように返却されるか違いを見ていきます。

$eloquent = User::where('id', 1);
$querybuild = \DB::table('users')->where('id', 1);

dump($eloqunet);
dump($querybuild);
exit();

返却値の解説:

見るだけでは、分かりづらいですが、

User::where('id', 1) は Illuminate\Database\Eloquent\Builder インスタンスを返します。

このオブジェクトは、Eloquentモデル(ここでは User モデル)に基づいてデータベースクエリを構築します。

したがって、これにより、モデルのリレーション、アクセサ、ミューテータなどのEloquentの機能を利用できます。

\DB::table('users')->where('id', 1) は Illuminate\Database\Query\Builder インスタンスを返します。

このオブジェクトは、テーブル名とそのクエリ構造のみを使用してデータベースクエリを構築します。

したがって、この方法ではEloquent特有の機能(リレーション、アクセサ、ミューテータなど)を利用することはできません。

Eloquent 独自のメソッド

Eloquentモデルに特有のメソッドが多数あります。

これらのメソッドは、関連するデータベースのレコードを扱ったり、Eloquentモデルのインスタンスに関連する操作を行ったりするために使用されます。

いくつかの例:

●save()メソッド:

hasManyやhasOneのような1対多または1対1のリレーションシップを持つモデルに対して使用します。

例えば、特定のユーザが所有する新しい注文を保存する場合、以下のように記述できます。

$user = App\Models\User::find(1);

$order = new App\Models\Order(['order_data' => $data]);

$user->orders()->save($order);

●attach(), detach(), sync()メソッド:

これらのメソッドはbelongsToManyリレーションシップ(多対多)を持つモデルに対して使用します。

例えば、特定のユーザが参加する新しいロールを関連付けたり、解除したり、更新したりする場合に使用します。

$user->roles()->attach($roleId);

// ロールをユーザから解除する(削除する)

$user->roles()->detach($roleId);

// ユーザのロールを一度に更新する(既存のものは解除し、新たなものは関連付ける)

$user->roles()->sync([$roleId1, $roleId2]);

これらのメソッドは、Eloquentが提供する豊富なAPIを通じて、関連するレコードを簡単に操作することを可能にしています。

Eloquentモデルのリレーションシップに対してのみ使用でき、クエリビルダや生のSQLでは使用できません。

どの取得方法を採用すれば良いの?

Laravelの公式ドキュメンテーションでは、データベース操作に対してEloquent ORMを推奨しています。

ただし、公式ドキュメンテーションではEloquent ORMとクエリビルダの両方について詳細に説明しています。

これは、Eloquentが必ずしもすべてのデータベース操作に最適な選択肢であるわけではないことを示しています。

Eloquentにもデメリットがあります。

例えば、パフォーマンスです。

Eloquentは多くの機能と利便性を提供しますが、これらは処理コストを伴います。

複雑なクエリを頻繁に実行する大規模なアプリケーションでは、クエリビルダや生のSQLクエリの使用を検討することもあります。

他にも、アプリケーションロジックへの依存があります。

アプリケーションのロジックをモデル層(Eloquent)に組み込みすぎると、アプリケーションがEloquentと密結合になり、他のフレームワークやライブラリに移行するのが難しくなる可能性があります。

Eloquentとクエリビルダのどちらを選択するかは、アプリケーションの要件、データベース操作の複雑さ、パフォーマンス要件など、具体的な状況によります。

それぞれの利用方法を理解し、自分のプロジェクトに最適なツールを選択することが重要です。

以上です、お疲れ様でした!!

最新の記事を公開する際には、X(旧Twitter)でもお知らせしています。
ご興味のある方は、ぜひフォローをお願いいたします!