Eloquentの準備 - 公式doc読む

Eloquentの準備

  • えろけんともでるの作り方
    • コントローラーとかも一緒に生成できるらしい、知らんかった
  • Eloquentモデルの規約(基礎ルール)
    • モデル名をスネークケースの複数形にしたのがテーブル名
      • それ以外にしたいなら、tableプロパティに設定する
    • 主キー
      • インクリメントのint
      • 複合主キーはダメ
    • タイムスタンプ
      • created_atとupdated_atは基本的に作られる
    • データベース接続
      • connectionプロパティに設定するとデフォルト以外のDBに接続できる
    • デフォルト値
      • モデルクラスで設定できる
      • へー
      • けど使わないね、なんでだろ?

モデルの取得

  • モデルの更新
    • flesh, refleshというメソッドがあり、取得済みのモデルクラスを更新できる
      • どういう使い道があるんだ?
  • コレクション
    • モデル経由して取得してるのはEloquentのコレクション
      • これのメソッドが便利なんだわ
    • chunk, lazy, cursor
      • でけえ処理をひとまとまりにしてやるやつ
      • メモリの節約になる

単一モデル/集計の取得

  • all()するとモデルコレクションが得られるけど、first()とかだとモデルインスタンスが得られる
    • なるほど、こういうふうに表現すればいいのか
  • 取得/例外 FindOrFail()
    • 見つからなかったら例外なげるクラス
    • キャッチしない場合は404になる
  • 取得/生成 findOrCreate, New
    • 取得できなかったら作る
      • これふつうに三項演算子でやってるケースあるな
    • パラメータでつくるCreate, 新しいモデルインスタンスを生成するだけのNew
  • 集計の取得
    • sum, count, maxなど
    • モデルクラスではなくintとかで返ってくるよ

モデルの挿入と更新

  • インスタンス作って、プロパティ渡して、save()すれば保存できる
  • update()はコレクションにも使える!! すご
    • このときモデルクラスは取得されていないので、モデルイベントが発生しない
  • 属性の変更の判断
    • isDirty, isClean, wasChanged
      • wasChangedはこのリクエストサイクルで、最後の保存処理に属性の変更があったかを判断する
    • getOriginal
      • 変更前をとる
  • 一括割り当てとJSONカラム
    • 翻訳下手
  • 更新/挿入
    • updateOrCreate()

モデルの削除

  • これら、物理削除してるの? それとも論理削除?
    • SoftDelete traitsをモデルに引き入れて、deleted_atをカラム追加するとできるらしい。
      • delete()使うだけで論理削除になる。
  • trancate()
    • モデルの静的メソッド
    • 全部のレコード消せる?
  • destroy()
    • idの値渡せば消してくれる
    • いちいちインスタンスを取得しなくて良い
  • コレクションに対するdelete()も可能
    • ただしモデルイベントが発生しない
  • 論理削除
    • 上記の通り、SoftDeleteトレイトを引き入れてやる
    • 論理削除されたレコードはすべてのクエリ結果から自動で除外される
      • ほんとか? インボイスのバッチやるときこれできてなかったよな?
  • 論理削除済みであることの確認
    • trashed()
  • 復元
    • restore()

モデルの整理

  • 不要な履歴レコードの削除など
  • plunableを引き込む
    • でplunable()で消されるレコードの定義
    • pluningで消す前にやってほしいことを定義
  • MassPrunableを引き込むと複数を一度に消せる
    • イベントが発生しない
    • pruningもおきない

モデルの複製

  • replicate()
    • 複製。保存はしない
    • これ他の手段でどうにかならないかな
      • いくつかのパターンがあるってことだから、いやまあいいのか

グローバルスコープ

  • SoftDeleteみたいな感じで、クエリ全体に制約を課すことが可能。
  • Illuminate\Database\Eloquent\Scopeインタフェースを実装することで可能。
    • こいつは決まった配置場所とかもない
    • んでapplyメソッドにwhereとかでクエリ書くと、その制限が適用される
      • selectはaddSelect
  • グローバルスコープの適用
    • モデルのbooted()をオーバーライドし、モデルのaddGlobalScope()を呼び出す。引数にはグローバルスコープのインスタンスを渡す
      • useでできるんとちゃうんかい
    • クロージャでの登録も可能。addGlobalScope()の第一引数にスコープ名、第二引数にクロージャを与える。
  • グローバルスコープの除外
    • 特定のクエリのみグローバルスコープの範囲外にしたいとき
      • クエリ呼ぶときにModelClass::withoutGlobalScope(グローバルスコープ名(ScopeClass::class))とする。

ローカルスコープ

  • 再利用容易なクエリ制約
    • モデルにscopeのプレフィックスをつけたメソッドを定義する
    • んで、プレフィックス除いたやつがselectとかみたいにクエリメソッドとして使えるようになる
      • 便利!
      • まあ普通にコレクション取得するメソッド書いてもいいんだけど。
  • パラメータを渡す
    • のも、可能。scopeメソッドに引数設定してあげればいいだけ
    • たぶん複数もいけるね
  • クエリの論理グループ

モデルの比較

  • is, isNot()でふたつのモデルの比較が可能
    • リレーションを使って比較するのも便利
  • morphToというリレーション
    • ポリモーフィックらしい。
    • 画像テーブルのデータがユーザーと記事に紐づいている、みたいな
    • すげえアンチパターンっぽいけどいいのかな
      • 実際アンチパターンだった

イベント

  • いろんなイベント
    • retrieved
      • データベースからのモデル取得時
    • saving, saved
      • モデルの属性に変化がなくても発行される
  • リッスンの仕方
    • dispatchEventsプロパティを使う
      • ここらへん、たぶんレバでtrait使ってんのは、traitにまとめてるんだろな
      • baseTrait作ってそれ継承したやつをモデルクラスごとに作り、引き込む
    • プロパティに渡すやつは、
      • イベントクラスつくる
      • コンストラクタでモデルを受ける
      • コンストラクタでそのモデルになんか操作する?
      • んで、そのイベントクラスをモデルのdispatchEventプロパティに設定してあげる
  • キューで処理することも可能
  • イベントをたくさん作る時は、モデルごとにオブザーバーを作ることも可能
    • イベントをまとめられる
    • コミット後にイベントを発火させることも可能
  • 感想
    • いろんなやり方がある
    • まー、クロージャでやればいいと思うが。
    • わざわざオブザーバーにしてもそんなにメリットないような?
  • イベントのミュート
    • withoutEvent()でイベントを起こさずに処理ができる
      • クロージャを引数に受け取る
    • saveQuietly()でイベントなしに保存可能