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()でイベントなしに保存可能