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

# 取得するとき

## 職人
```php
User::find(1);
```

## ナイス職人
```php
User::active()->createdLastMonth()->get();
```

Userクラスにクエリースコープを作って、それを使う
クエリースコープは下記のようになる

```php
class User extends Model
{
    public function scopeActive($query)
    {
        $query->where('active', true);
    }
}
```

## ほぼSQL書いてる急ぎの職人
```php
User::where('active', true)->where('created_at', '>', Carbon::now()->subMonth())->get();
```
ここはもうSQLを書くことに近づいてきてるね
便利だけど、気をつけてください！
これはすごくメンテしにくいコードに進むパターンだ。

# データを入れるとき（インサートでも、アップデートでも）

## 職人
```php
$user->fill($request->all())->save();
```

`fill()`を使うと、Eloquentは`$fillable`をチェックして、このプロパティを設定できるかどうかを確認してくれるね。
`$fillable`を無視したい場合は`forceFill()`を使うけど、気をつけてね！
普通、`forceFill`を使うのはデータベースシーダーとかだね。


## 書くことが好きな職人

```php
$user->name     = $request->name;
$user->email    = $request->email;
// ... 永遠に続くorz
$user->birthday = $request->birthday;
$user->save();
```

これはそんなに悪いパターンじゃないけど、フィールドの数が多いほど、悪いパターンになっていく。
そして、この方法は`$fillable`を無視するから、注意！できるだけ`fill()`にしてください

## メソッド名に騙されてる可能性が高い人

```php
$data = ['name' => 'Shintarou', 'is_administrator' => true];

$user->update($data);
```

直接SQLでデータを入れてるだけですね。
SQLを使えるのは力強いほど危険で、気をつけないとね。
上の例えで、データが`$request->all()`から来てる場合、`update($data)`することで、なるはずのない誰かが管理者になるかもしれない。

もちろん、`update()`使いたいときもあります！

```php
User::haveNotLoggedOnForFewMonths()->update(['inactive' => true]); 
```

複数行にアップデートをしたいときには完璧だね！


# 作成するとき

##　職人

```php
User::create($data);
```

これは一番簡単な方法だね！読みやすいから使われるけど、実際には下記のようになっている

```php
public static function create(array $attributes = [])
{
    $model = new static($attributes);

    $model->save();

    return $model;
}
```

ということで、下記のように書いてもおｋ！同じことになる。

```php
(new User($data))->save();
```

## 使う場合を考えられなかったけど、一応ある方法

```php
User::insert($data);
```

SQLの`update()`ができるように、SQLの`insert()`もできます…　ちゃんとした理由がないと使わないでくださいね。
これはタイムスタンプを自動的に入れないし、`$fillable`もチェックしてくれないんだ。

# 削除するとき

## 職人

```php
User::find(1)->delete();
```

モデルを取得してから削除する。
注意：SELECT（`find`）してから、DELETEをしている。クエリーは２つ
 

## PKだけで削除できる職人

```php
User::destroy(1);
User::destroy([1, 2]);
```

取得せずに削除してる。クエリーは１つ

## 職人かもしれない、メソッド名に騙されてる人かもしれない

```php
User::whereActive(false)->delete(); 
```

updateとinsertと同じ、SQL向きのメソッドだ。
複数行で削除したいなら、便利だけど注意が必要

直接でSQLのDELETEだから、Userクラスにたとえ、SoftDeletesのTraitがあったとしても、`deleted_at`をアップデートせずに、その１行がデータベースから消される。
それはもちろん危ないし、誰も望んでいないことだから、そのとき狙いはきっと下記のようなコードだね。

```php
User::whereActive(false)->update(['deleted_at' => Carbon::now()]); 
```

だけど、今回は削除するロジックは２つの場所になるね… EloquentのSoftDeletesのTraitを使いたいね！

```php
$inactiveUserIds = User::whereActive(false)->lists('id');
User::destroy($inactiveUserIds);
```

すべてのIDを取得してから、クエリー１つですべてのIDをEloquentで削除する :smile: 

# 結論

この記事の目的はどこでEloquentのパワーフルなモデルから、自由なQuery BuilderでSQLになることを別々にすることだね。

`User::where()`みたいなメソッドを使うときは、EloquentのQuery Builderのインスタンスをもらうから注意！

そのQuery Builderオブジェクトに`insert()`、`update()`、`delete()`を呼ぶとモデルのいろんな設定を無視して、単純にSQLとして行われる。


# 推敲

```php
// 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を行う

// ３つも同じ
$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を行う
```