取得するとき
職人
User::find(1);
ナイス職人
User::active()->createdLastMonth()->get();
Userクラスにクエリースコープを作って、それを使う
クエリースコープは下記のようになる
class User extends Model
{
public function scopeActive($query)
{
$query->where('active', true);
}
}
ほぼSQL書いてる急ぎの職人
User::where('active', true)->where('created_at', '>', Carbon::now()->subMonth())->get();
ここはもうSQLを書くことに近づいてきてるね
便利だけど、気をつけてください!
これはすごくメンテしにくいコードに進むパターンだ。
データを入れるとき(インサートでも、アップデートでも)
職人
$user->fill($request->all())->save();
fill()を使うと、Eloquentは$fillableをチェックして、このプロパティを設定できるかどうかを確認してくれるね。
$fillableを無視したい場合はforceFill()を使うけど、気をつけてね!
普通、forceFillを使うのはデータベースシーダーとかだね。
書くことが好きな職人
$user->name = $request->name;
$user->email = $request->email;
// ... 永遠に続くorz
$user->birthday = $request->birthday;
$user->save();
これはそんなに悪いパターンじゃないけど、フィールドの数が多いほど、悪いパターンになっていく。
そして、この方法は$fillableを無視するから、注意!できるだけfill()にしてください
メソッド名に騙されてる可能性が高い人
$data = ['name' => 'Shintarou', 'is_administrator' => true];
$user->update($data);
直接SQLでデータを入れてるだけですね。
SQLを使えるのは力強いほど危険で、気をつけないとね。
上の例えで、データが$request->all()から来てる場合、update($data)することで、なるはずのない誰かが管理者になるかもしれない。
もちろん、update()使いたいときもあります!
User::haveNotLoggedOnForFewMonths()->update(['inactive' => true]);
複数行にアップデートをしたいときには完璧だね!
作成するとき
職人
User::create($data);
これは一番簡単な方法だね!読みやすいから使われるけど、実際には下記のようになっている
public static function create(array $attributes = [])
{
$model = new static($attributes);
$model->save();
return $model;
}
ということで、下記のように書いてもおk!同じことになる。
(new User($data))->save();
使う場合を考えられなかったけど、一応ある方法
User::insert($data);
SQLのupdate()ができるように、SQLのinsert()もできます… ちゃんとした理由がないと使わないでくださいね。
これはタイムスタンプを自動的に入れないし、$fillableもチェックしてくれないんだ。
削除するとき
職人
User::find(1)->delete();
モデルを取得してから削除する。
注意:SELECT(find)してから、DELETEをしている。クエリーは2つ
PKだけで削除できる職人
User::destroy(1);
User::destroy([1, 2]);
取得せずに削除してる。クエリーは1つ
職人かもしれない、メソッド名に騙されてる人かもしれない
User::whereActive(false)->delete();
updateとinsertと同じ、SQL向きのメソッドだ。
複数行で削除したいなら、便利だけど注意が必要
直接でSQLのDELETEだから、Userクラスにたとえ、SoftDeletesのTraitがあったとしても、deleted_atをアップデートせずに、その1行がデータベースから消される。
それはもちろん危ないし、誰も望んでいないことだから、そのとき狙いはきっと下記のようなコードだね。
User::whereActive(false)->update(['deleted_at' => Carbon::now()]);
だけど、今回は削除するロジックは2つの場所になるね… EloquentのSoftDeletesのTraitを使いたいね!
$inactiveUserIds = User::whereActive(false)->lists('id');
User::destroy($inactiveUserIds);
すべてのIDを取得してから、クエリー1つですべてのIDをEloquentで削除する ![]()
結論
この記事の目的はどこでEloquentのパワーフルなモデルから、自由なQuery BuilderでSQLになることを別々にすることだね。
User::where()みたいなメソッドを使うときは、EloquentのQuery Builderのインスタンスをもらうから注意!
そのQuery Builderオブジェクトにinsert()、update()、delete()を呼ぶとモデルのいろんな設定を無視して、単純にSQLとして行われる。
推敲
// 3つも同じ結果だけど…
User::where('id', 1)->get()[0]; // 読みづらい
User::where('id', 1)->first(); //
User::find(1); // 読みやすい
User::find(1)->fill($data)->save(); // Eloquent Modelとしてアップデートする
User::where('id', 1)->update($data); // Query BuilderのUPDATEを行う
// 3つも同じ
$user0 = User::create($data);
$user1 = new User($data);
$user1->save();
$user2 = (new User)->fill($data);
$user2->save();
User::find(1)->delete(); // Eloquent Modelを取得してから、削除する
User::where('id', 1)->delete(); // Query BuilderのDELETEを行う