[Laravel]Eloquent ORMとクエリビルダについて　~備忘録~

##はじめに
この記事はプログラミング初学者による備忘録用の記事であり、また、少しでも他の初学者のお役に立てればと思い書いています。

今回は、LaravelのEloquent ORMとクエリビルダの特徴や違いについて再考したので、備忘録としてまとめておきたいと思います。

間違いなどがございましたら、ご指摘のほどよろしくお願い致します。

##Eloquent ORMとは
Eloquent ORMとは、Laravelに含まれているアクティブレコードによるデーター操作機能です。

###・特徴
・Eloquentでは、**ファサードの宣言は不要**ですが、利用するモデル名に関してはクエリビルダと同様にuse宣言に入れる必要があります。

・特定のモデルにどのテーブルを使用するか、Eloquentに指定する必要がありません。他の名前を明示的に指定しない限り、クラス名を複数形の「スネークケース」にしたものが、テーブル名として使用されます。

・**Eloquentモデルはクエリビルダとしても動作する**ので、クエリに制約を付け加えることもでき、結果を取得するにはgetメソッドを使用します。

・**複数の結果を取得するallやgetのようなEloquentメソッドの戻り値**は、**オブジェクト型の**``Illuminate\Database\Eloquent\Collection``となっており、CollectionクラスはEloquent結果を操作する[多くの便利なクラス](https://readouble.com/laravel/6.x/ja/eloquent-collections.html#available-methods)を提供しています。
この[Collection](https://readouble.com/laravel/6.x/ja/eloquent.html#collections)は配列のようにループさせることもできます。

・複雑なDB操作が可能なメソッドが数多く用意されています。

###・基本的な記述例
下記の例では、UserモデルとPostモデル間でリレーションがある場合を想定し、UserモデルでJunという名前のnameに該当する、Postモデルのデータを参照しています。

**Eloquentでは、モデル間でリレーションがある場合、予めお互いのモデルファイルに下記のようにリレーションを定義しておく必要があります。**

```.php
//リレーションの定義
class User extends Authenticatable
{
 public function posts(): HasMany
    {
      return $this->hasMany('App\Models\Post');
    }
}

class Post extends Model
{
    public function user(): BelongsTo
    {
        return $this->belongsTo('App\Models\User');
    }
}

//Eloquentでのデータ取得
$user = User::where('name', 'Jun')->first( );
$posts = $user->posts;
```
その他、Eloquentに関する詳細は、[リンク先の公式ドキュメント](https://readouble.com/laravel/6.x/ja/eloquent.html)をお読みください。

###・戻り値のデータ形式
・複数の結果を取得する**allやgetのようなEloquentメソッド**の場合
``オブジェクト型のIlluminate\Database\Eloquent\Collectionインスタンス``を返します。

・**findやfirst、firstWhereメソッド**を使い１レコードだけを取得する場合
``モデルインスタンス``を返します。

##クエリビルダとは
クエリビルダとは、SQL文を簡単に組み立てて、データベースの操作をしやすくしたものです。

###・特徴
・Laravelでクエリビルダを使用するには、最初に**DBファサード**をuse宣言する必要があります。

・リレーションなどは、自分で把握して結合する必要があります。

・記述がSQL文に近い形式なので、ある程度のSQL文に関する知識が必要とされます。

・**戻り値はコレクション(Illuminate\Support\Collection)となっています**。

###・基本的な記述例
クエリビルダを書く際は、まず初めに``Illuminate\Support\Facades\DB;``と``データを取り出す対象となるテーブルのモデル名``をuse宣言してから``DBファサードのtableメソッド``を使用します。
tableメソッドは、指定したテーブルに対するクエリビルダインスタンスを返し、これを使いクエリに様々な制約を追加して、最終的な結果を``get()``で取得します。

下記の例では、UserモデルとPostモデル間でリレーションがある場合を想定し、UserモデルでJunというnameのidに該当する、Postモデルのデータを参照しています。

```.php
use Illuminate\Support\Facades\DB;

$users = DB::table('users')
->join('posts', 'users.id', '=', 'posts.user_id')
->where('name', 'jun')
->get();
```
クエリビルダに関する詳細は、[リンク先の公式ドキュメント](https://readouble.com/laravel/8.x/ja/queries.html)をお読み下さい。

###・戻り値のデータ形式
・DBファサードのtableメソッドを使い**getメソッド**でデータを取得する場合
``get() -> Illuminate\Support\Collection``を返す

・データベーステーブルから１レコードのみ取得する**firstメソッド**の場合
``first() -> stdClassオブジェクト``を返す


##クエリビルダとEloquentの比較

|特徴|Eloquent|クエリビルダ|
|:--|:--:|:--:|
|リレーションの定義が必要|○|×|
|Modelの定義が必要|○|×|
|SQLの知識|あまり必要ない|ある程度の知識が必要|
|SQLインジェクション対策|○|○|
|クエリビルダが利用可能|○|○|

##補足
###・Eloquentでもクエリビルダが使用できる

>
Tip!! Eloquentモデルはクエリビルダですから、クエリビルダで使用できる全メソッドを確認しておくべきでしょう。
Eloquentクエリでどんなメソッドも使用できます。
[Laravel6.x Eloquent](https://readouble.com/laravel/6.x/ja/eloquent.html?header=%25E3%2582%25B0%25E3%2583%25AD%25E3%2583%25BC%25E3%2583%2590%25E3%2583%25AB%25E3%2582%25B9%25E3%2582%25B3%25E3%2583%25BC%25E3%2583%2597%25E3%2581%25AE%25E8%25A8%2598%25E8%25BF%25B0)

```.php
//例
$user = User::find(1);
```

###・どちらもSQLインジェクション攻撃から守られている
>
LaravelクエリビルダはアプリケーションをSQLインジェクション攻撃から守るために、
PDOパラメーターによるバインディングを使用します。バインドする文字列をクリーンにしてから渡す必要はありません。
[Laravel6.x クエリビルダ](https://readouble.com/laravel/6.x/ja/queries.html?header=%25E3%2582%25A4%25E3%2583%25B3%25E3%2583%2588%25E3%2583%25AD%25E3%2583%2580%25E3%2582%25AF%25E3%2582%25B7%25E3%2583%25A7%25E3%2583%25B3)

クエリビルダやEloquentは、アプリケーションをSQLインジェクション攻撃から守るために、PDOパラメーターによるバインディングを使用しています。

##まとめ
LaravelのEloquent ORMとクエリビルダ、どちらを利用してデータ操作を実行するべきかの具体的な答えは出ていませんが、私の考えとしましてはEloquent ORMを利用したデータ操作の方が可読性が高くコードのメンテナンスもしやすいと感じた為、基本的にはEloquent ORMを利用したいと思います。


##参考文献
[Laravel6.x クエリビルダ](https://readouble.com/laravel/6.x/ja/queries.html)
[Laravel6.x Eloquent 利用の開始](https://readouble.com/laravel/6.x/ja/eloquent.html)
[Laravel6.x Eloquent Collection](https://readouble.com/laravel/6.x/ja/eloquent-collections.html)