Slide 1

Slide 1 text

Eloquent Driven Development 2019/10/31 YamaYuski Infiniteloop

Slide 2

Slide 2 text

YamaYuski a.k.a 赤魔導士 こないだ PHP カンファレンス北海道 2019 に登壇しました 前回も発表しました

Slide 3

Slide 3 text

RDB インテグレーション Laravel Databases

Slide 4

Slide 4 text

Laravel DB 下記 Relational DB に対応 - MySQL - PostgreSQL - SQLite - SQL Server 内部では PDO を利用している .env とコンフィグファイルで接続情報を指定 複数の RDB を同時に扱うことも可能

Slide 5

Slide 5 text

Query Builder 一般的な Fluent Query Builder を搭載 大多数のクエリはクエリビルダで完結可能

Slide 6

Slide 6 text

Migration 複数 RDB に対応した マイグレーションを搭載 PHP でマイグレーションファイルを 書くことで自動で SQL 化 コマンドで手軽に適用

Slide 7

Slide 7 text

Factory ランダムレコード生成器 テスト時手軽に 必要なレコードを生成出来る => Laravel は DB 依存テストが簡単! テストだけ sqlite も可能!

Slide 8

Slide 8 text

Faker? それっぽいダミー値を生成してくれるライブラリ 各言語用のモジュールも搭載(佐藤 太郎とか John Doe とか) 様々なダミー値を生成出来る面白い奴

Slide 9

Slide 9 text

エ↑レクヮント↓(能弁な, 雄弁な) - éləkwənt Eloquent

Slide 10

Slide 10 text

Eloquent ORM? - Active Record 型(自律型) Object-Relational Mapper - モデルクラス自身がクエリを発行する - RDB テーブルと 1 対 1 で紐づくモデルクラス - `users テーブル` -> `class User extends Model` - 1 インスタンスが 1 レコード - 山ほど機能を搭載

Slide 11

Slide 11 text

“ 郷に入っては郷に従え 17 Tips

Slide 12

Slide 12 text

1. テーブル名・クラス名は明瞭にしよう 名は体を表す テーブル名とクラス名は 必ずしも一致しなくて良い テーブル名はリストで見る用に クラス名は外部キー名に使う 暗黙テーブル名は避けよう Str::snake(Str::pluralStudly(class_basename($this)))

Slide 13

Slide 13 text

2. プライマリキーは `id` にしよう リレーション含めデフォルトの扱いが `id` という名前 余計な設定を増やさないために、基本は `id` にしよう

Slide 14

Slide 14 text

3. マイグレーションを手軽にやろう どの RDB でも同じマイグレーション ファイルで実行可能(制限はある) よく使う PK AUTO_INCREMENT などの エイリアスが豊富 created_at, updated_at も一行

Slide 15

Slide 15 text

4. $table->timestamps() は気を付けよう 基本は全テーブルに `created_at` `updated_at` TIMESTAMP カラム MySQL TIMESTAMP 型は 2038 年までしか保持出来ないので気を付けよう

Slide 16

Slide 16 text

5. Model を作ったら Factory も作ろう テストしたり Seeding する時に活用出来る よくあるステートごとに state 定義を増やして手軽に生成しよう

Slide 17

Slide 17 text

6. $dates, $casts で手軽にキャストしよう `declare(strict_types=1);` の時に活用出来る 0, 1 の値を boolean としたり 日時を Carbon としたり json の値を array としたり出来る PDO 的に基本全部 string で返ってくるので 自動キャストは便利!

Slide 18

Slide 18 text

7. 垂直分割時は $connection を指定しよう DB をまたぐ join をしないように注意 そもそも Active Record で join は微妙(最適化必須の所だけにしよう)

Slide 19

Slide 19 text

8. $attributes は設定しないようにしよう デフォルト値は RDB 側の DEFAULT 制約でまかなおう

Slide 20

Slide 20 text

9. @property をつけよう laravel-ide-helper が自動で付けてくれる IDE でプロパティの補完が効くようになる

Slide 21

Slide 21 text

10. Local Scope で where 句に名前をつけよう クエリビルダを拡張出来る 命名出来るって大事! @method active() と書けば 少し IDE 補完サポートも得られる

Slide 22

Slide 22 text

11. Routing Explicit Model Binding を使おう API 中で PK 指定する場合は Explicit Model Binding でモデルを取得

Slide 23

Slide 23 text

12. Policy を設定して認可を手軽に実装しよう このユーザが特定の Model に対して 何が出来るかを定義する @can Blade Directive とかで 簡単に使える

Slide 24

Slide 24 text

13. API Resources でレスポンスさせてみよう Model を json として返す時の型として使える RESTful API っぽいものを作る時に便利

Slide 25

Slide 25 text

14. テストに RDB を用いよう ユニットテストでも RDB を使ってしまえば、モックやスタブを書かなく てすむし、 DB 依存の問題も発見出来る テストが遅くなるが、そこは並列化とかでカバー

Slide 26

Slide 26 text

15. コマンド・クエリ責務分離(CQRS) を使おう トランザクションが必要な追加・更新・削除処理をコマンド 取得だけの処理をクエリ と考えて関心を分離し、コマンドは厳密に、クエリは高速になるよう書く クエリ側では Eloquent を使わなくても良いかも

Slide 27

Slide 27 text

16. CarbonImmutable を使ってみよう Carbon 2.0 から追加された DateTimeImmutable な Carbon これで clone() し忘れてバグることもなくなる!

Slide 28

Slide 28 text

17. DB::listen でクエリログを収集しよう DB::listen(callable $callback) で SQL と実行時間を取得出来る デバッグ環境では EXPLAIN を追加発行して、問題のあるクエリでないか ログで確認出来るように拡張しよう パスワードなどの bindings をログに残さないように気を付けよう laravel-debugbar がうまいことその辺やってくれるのでオススメ json API の場合は代わりにログなどに吐くようにしよう

Slide 29

Slide 29 text

Fin. 1. テーブル名・クラス名は明瞭にしよう 2. プライマリキーは `id` にしよう 3. マイグレーションを手軽にやろう 4. $table->timestamps() は気を付けよう 5. Model を作ったら Factory も作ろう 6. $dates, $casts で手軽にキャストしよう 7. 垂直分割時は $connection を指定しよう 8. $attributes は設定しないようにしよう 9. @property をつけよう 10. Local Scope で where 句に名前をつけよう 11. Routing Explicit Model Binding を使おう 12. Policy を設定して認可を手軽に実装しよう 13. API Resources でレスポンスさせてみよう 14. テストに RDB を用いよう 15. コマンド・クエリ責務分離(CQRS) を使おう 16. CarbonImmutable を使ってみよう 17. DB::listen でクエリログを収集しよう