Help us understand the problem. What is going on with this article?

LaravelのORMで初心者から職人へ

More than 1 year has passed since last update.

取得するとき

職人

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で削除する :smile:

結論

この記事の目的はどこで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つも同じ
$user = User::create($data);
$user = new User($data)->save();
$user = new User()->fill($data)->save();

User::find(1)->delete();        // Eloquent Modelを取得してから、削除する
User::where('id', 1)->delete(); // Query BuilderのDELETEを行う
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした