Closed14

Laravelのメモ

やむ🏔やむ🏔

CodeSniffer

コードをクリーンに保てる(PSR-12準拠など)
公式Docが読みづらいけど面倒だと思ったルールは追記もしくは除外していった方が良き
CIに組み込んでエラー出たら弾く感じがベター。ルールはみんなで考えようね。

https://github.com/squizlabs/PHP_CodeSniffer

ref

https://pleiades.io/help/phpstorm/using-php-code-sniffer.html#installing-configuring-code-sniffer
https://qiita.com/blue32a/items/db049e091d4e7a469e6d
https://github.com/squizlabs/PHP_CodeSniffer/wiki/Annotated-Ruleset

やむ🏔やむ🏔

PHPStan

静的言語なんじゃないかくらい精査してくれる安全保証マン
Laravelには別途larastanっていう最適化されたやつがあるので、そっちを使うとヨシ!
こいつもCI常連理事
レベルは0でも良いけど運用的には6くらいが楽かなぁ〜という肌感。8まで行くと効率落ちそう

https://github.com/phpstan/phpstan
https://github.com/nunomaduro/larastan

ref

https://blog.shin1x1.com/entry/getting-stated-with-phpstan

やむ🏔やむ🏔

Carbon

Laravelで日時扱う時に便利なライブラリ。CarbonとCarbonImmutableというクラスが2個あって、前者は可変的かつメソッドが破壊的なので注意(初見時ハマった)

https://carbon.nesbot.com/

やむ🏔やむ🏔

Timezoneについて

shiftTimezone(tz) タイムゾーンを切り替える(差分計算は行わない)
timezone(tz) タイムゾーンを切り替える(差分計算を行う)

Model::factory()->create($data)で日付の値を指定した時はアプリの設定関係なしで指定した時間がDBに登録される

逆にアプリ内で保存処理をする際はLaravelのapp.phpに書かれているtimezoneに変換されてDBに登録される

やむ🏔やむ🏔

テスト関係

プライベートメソッドに対してテストを書くな

privateの時点でどこかしらから呼ばれているのでテストはそっちでカバーしてださい。
privateメソッドのテストを書くとなるとリフレクション書く必要があってテストコードの見通しが悪くなります(保守性がグッと落ちます)
リフレクション書くのめんどくさいしpublicにしちゃえばよくね!wってなる可能性も0じゃ無いので大人しくprivateは呼び出し先でテストをやりましょう。

RefreshDatabase

テストを回すのに時間がかかるようになるので使いすぎには注意。
あとできればリポジトリ触る系のコードはアプリケーション層に閉じ込めて、ドメイン層ではモデルだけいじる感じの分離ができたら理想かなぁと考えています。

RefreshDatabaseはprotected $seeder = SomeTableSeeder::class;すればシーディングもしてくれる。

Factoryに書く要素

Factoryはささっとデータを用意したい時に便利なんだけど、みんながみんな使う場所なので影響範囲がでかい。
なのでここで要素を決めすぎると辛い時があるので、必須要素だけFactoryで定義すると良いのかも?
Factoryでリレーションを作ってしまうのも考えられるけど、そうなるとモデルだけ使いたい時にもRefreshDatabaseが必要になりそうなので避けるべきかなぁと感じています。

AAAパターン

PHPUnitのテストメソッドはなるべくAAA(アレンジ・アクション・アサート)の構成で書きたいです。
なのでこの構成に従うとしたら、dataProviderはテストメソッドのすぐ上に書くべきだと思います。(Arrange部にあたる)
dataProviderの紹介記事では下に書いていることが多いので、上に書くように啓蒙していきたい。

リファレンスデータはヘルパーに追いやりたい

リファレンスデータ(参照用テーブル)は一々Factoryで書いたり、Seeder使うのは少し面倒なので、テストヘルパーメソッドに分離して、呼び出すだけでリファレンスデータは用意したい。

Factoryを使ったらidを決め打ちで書くな

テストでレコードのid決め打ちで書くと死にます。なるべくFactoryの戻り値のidを使って指定するようにしましょう。
そうするとリファレンスデータをヘルパーメソッドにした時どうするみたいなことになるので、少し悩みどころ。

markInComplete

$this->markInComplete() を使うとテストをスキップできます。
スキップしたい時もあるでしょうが、割れ窓になる可能性があります。
もしどうしてもスキップしたい時は、スキップすることになった変更の内容のコミットへのリンクなどを@refとかで貼っておくとテストがメンテしやすくなります。
メンテされないままで放置されるテストは書く意味がほとんどなく、無駄です。

setUpにどこまで書くか

setUpに集約しすぎると辛い可能性があります。悩みどころです・・・。
変更箇所が減るためメンテ性は上がるんですが、可読性が落ちます。ここはバランスを考えつつなので、最適解はなしって感じになるかもしれないです。

複雑なデータが必要だったら関数分けてもいいかも

Userデータも必要だし、Bookデータも必要だし、RentHistoryも必要だし、UserRewardも必要だし・・・みたいに複数のデータが必要になるとFactoryだけでもテストメソッドが膨張します。
テストメソッドが膨張すると可読性が落ちるので、保守性も落ちます。
なのでprivateで別にfactoryするメソッドを用意してしまいましょう。その関数で引数を受け取るようにすればdataProviderで動的にfactoryもできるのでベスト

こんな感じ(テーブルとかは完全に適当なので注意)

private function factoryPreRequirements(array $userData, array $bookData): array
{
    $user = User::factory()->create($userData);
    $book = Book::factory()->for($user)->create($bookData);
    $rentHistory = RentHistory::factory()->for($user)->for($book)->create();

    return [
         'user' => $user,
         'book' => $book
    ];
}
やむ🏔やむ🏔

トラップ

LaravelはRequestパラメータはStringで受けとる。rulesで型指定しようが無駄

このスクラップは2022/07/02にクローズされました