LaraveのEloquentについて
LaravelのEloquentとは?
EloquentはActive RecordライクなORMで、DBとモデルを関連付けてデータ操作をすることが可能。
※Active Recordとは Active RecordはDBからデータを読み出すための手法。DBのtableまたはviewの1行が1つのクラスにラップされ、オブジェクトのインスタンスがそのデータベースの1つの行に結合される。SQLを意識せずにデータベースアクセスを行うことができる。
モデルの作成
Eloquentを利用するにはモデルが必要なのでモデルを作成する
php artisan make:model Task
モデルとDBのテーブルとの関連付けは、テーブル名を複数形、モデルを単数形で作成すると暗黙的に関連付けられる。
例) テーブル名 → tasks モデル名 → Task
テーブル名がスネークケースの場合は、モデルをキャメルケースで作成すると関連付けられる。
例) テーブル名 → task_sample モデル名 → TaskSample
上記2つを適用しない場合は、$tableプロパティで指定し関連付けることができる。
データ検索/更新などの基本メソッド
よく使う基本的なメソッドを以下にまとめる。
全件抽出 all
テーブルの全レコードを取得するメソッド 戻り値はCollectionで、Collectionの要素はModelクラスのインスタンス。
$tasks = Task::all();
PrimaryKey指定での抽出 find
,findOrFail
find
引数にPrimaryKeyを指定して、合致するレコードのみ取得する。 戻り値はModelのインスタンス。
$task = Task:find(10);
findOrFail
findと似てるが、該当レコードが見つからなかった場合、ModelNotFoundException
を投げる
try { $task = Task::findOrFail(10); } catch (ModelNotFoundException $e) { // 見つからなかった場合の処理 }
条件指定による抽出 whereXX
SQLのwhere区に相当する条件を引数に指定し、絞り込みを行えるメソッド。 XXにはテーブルのカラム名が入る。
$task = Task::whereTitle('タスクタイトル')->get();
レコードの登録 create
save
firstOrCreatre
create
配列を引数に指定して、レコードを登録できる。
Task::create([ 'title' => 'タスクタイトル', 'content' => 'タスクの内容' ]);
save
対象のモデルのインスタンスを新規作成し、各カラムの値を設定し登録できる。
$task = new Task; $task->title = 'タスクタイトル'; $task->content = 'タスクの内容';
firstOrCreatre
ある条件でレコードを抽出し、レコードが見つからない場合のみ新規登録する。
$task = Task::firstOrCreatre(['title' => 'タスクタイトル']);
レコードの更新 update
更新対象のインスタンスに対して、更新したいカラムと値の配列を引数に指定しレコードを更新できる。
$task = Task::find(1)->update(['title' => 'タスクタイトル2']);
レコード削除 delete
, destroy
delete
削除対象のインスタンスに使用し、レコードを削除できる。
$task = Task::find(1); $task->delete();
destroy
削除対象のPrimaryKeyを指定し、レコードを削除する。
Task::destroy(1);
関連があるテーブル群をまとめて操作する
DBのテーブルは他のテーブルと関連していることが多い。 例えば、ユーザー(users)は複数のタスク(tasks)を持っている、など。 Eloquentはテーブルの関係性を踏まえて処理することができるリレーションという機能を持っっている。 以下はユーザー(users)、タスク(tasks)、カテゴリー(categories)の例で記述していく。
1対1 hasOne
, belongsTo
例)書籍(books)テーブルと書籍詳細(book_details)テーブル
第1引数に関連付けるモデル名、第2引数に内部キー、第3キーに外部キーを指定することができる。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Book extends Model { public function detail() { return $this->hasOne(BookDetail::class); } }
逆はbelongsTo
で指定することができる。
1対多 hasMany
例)ユーザー(users)テーブルとタスク(tasks)テーブル
<?php namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { public function tasks() { return $this->hasMany(Task::class); } }
hasOne
と同様に、第1引数に関連付けるモデル名、第2引数に内部キー、第3キーに外部キーを指定することができる。
逆は、belongsTo
で指定できる。
多対多 belongsToMany
例)タスク(tasks)テーブルテーブルとカテゴリ(categories)テーブル
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Task extends Model { public function categories() { return $this->belongsToMany(Category::class); } }
hasOne
と同様に、第1引数に関連付けるモデル名、第2引数に内部キー、第3キーに外部キーを指定することができる。
逆もbelongsToMany
で指定できる。
多対多では、結果コレクションに中間テーブル情報が付与されてくる。 これを取得したくないときは、モデルに$hiddenを定義することで除外できる。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Task extends Model { // 中間テーブル情報を取得しない protected $hidden = ['pivot']; public function categories() { return $this->belongsToMany(Category::class); } }
中間テーブルのカラムを取得したい場合はモデルに取得したいカラムを指定しておき、取得時にpivotプロパティにアクセスする。
<?php namespace App; use Illuminate\Database\Eloquent\Model; class Task extends Model { // 中間テーブル情報を取得しない protected $hidden = ['pivot']; public function categories() { return $this ->belongsToMany(Category::class, 'task_category_ref') ->withPivot('task_id', 'category_id') } }
Has Many Through
テーブルをまたぐリレーションを行うことができる。 以下の例で考える。
users ⇅ ⇅ roles tasks
rolesからusersを経由してtasksを取得したい時
<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Role extends Model { public function tasks() { return $this->hasManyThrough(Task::class, User::class); } }
第1引数にリレーションを行うモデル、第2引数には経由するモデルを指定する。