2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
Laravel クイズ (for Qiita Night) (全1記事)
リンクをコピー
記事をブックマーク
mpyw氏:「Laravelクイズ ~Qiita Night PHP 2023 Winter~」ということで始めます。よろしくお願いします。今回は「Qiita」のスライドを使わせてもらっています。(倍率が)100パーセントだと見にくかったので、50パーセントでだいぶ縮小して表示しています。自己紹介をしていると時間がないので、さっさと始めていきます。
以前の問題。最初に作ったLaravelクイズがあって、それに続き弊社の@fuwaseguくんが作ってくれた問題があって、(さらに)それに続いて第3弾ということで、今回また私から出題させてもらった内容になります。
以前から「Twitter」上、「X」上でこの問題については共有していたので、それのおさらいというか。今回初めて見る方もいると思いますが、その方向けにけっこう丁寧に説明しながら、知っている方はおさらいという感じで見てもらえれば幸いです。
じゃあ進めていきます。第1問。PUT users/
1番がプロパティアクセスでuserを取り出す。2番がget()というメソッドを使って取り出す。3番がinput()というメソッドを使って取り出す。4番がall()というメソッドを使って取り出したあと、userというキーにアクセスする。
1個だけ非常に危うい動作をするものがあります。5秒ぐらい待ちます。
ちょっと時間もないので発表にいきます。正解は1番ですね。$request->userでアクセスをすると非常に危険です。正しく内容がPOSTされた時は$request->input('user')と等価の動作を取るんですが、そのリクエストの$requestペイロードの中にuserというものが存在しない時、なんとこのコントローラーの引数にあるUser $userの値を取りにいってしまいます。
リクエストの中身かもしれないし、そのモデルそのもののオブジェクトを取ってしまうかもしれないということで、ぜんぜん違うものを取ってしまう可能性があるので、この書き方はできれば使わないようにしてほしいです。これは以前に私がQiitaで書かせてもらった記事のおさらいになります。
他のものに関して軽く説明しておくと、2番の$request->get('user')はたぶん見たことがある方はほとんどいないかと思いますが、一応Laravelでちゃんと存在しています。中身は(スライドに)書かせてもらったとおり、Symfonyのベースとなっているリクエストを継承しているだけの処理になります。
Laravelでよくある、JSON形式を解釈してドットチェインでキーを指定して中身を取り出すという動作をとることができないので、実質ちょっと使い勝手が悪い。$_POSTしかハンドリングができないので実用性はちょっと薄いかなということで、豆知識程度に覚えておいてください。
$request->input('user')に関しては説明不要ですね。もっともよく使われるものです。とりあえずこれを使っておけば困らないと思います。$request->all()に関しては同等の動きなので、特に説明はいらないかなと思います。
じゃあ次にいきます。2問目。Eloquent Modelのスコープ機能に関して、以下のうち使い方が間違っているものが1つだけあります。
1番。グローバルスコープという機能に関して、そのapply()メソッドで受けた$queryという変数にそのままWHEREとかをチェインして条件を付与していく。2番が、新しいクエリインスタンスを作り直して、それをリターンする。既存のオブジェクトを編集するというよりは新しいものをリターンするという動きですね。3番、4番がそれのローカルスコープ版になります。
次のうち、1個だけ動作として間違っているものがあります。じゃあ5秒ほど待ちます。
じゃあ正解を発表します。正解は2番です。グローバルスコープクラスに関しては、返り値がインターフェイス上でvoidと記述されているのでちょっと不便ですが、これに逆らうことはできないです。
どうしてもインスタンスごと入れ替えたいような処理があったら、ローカルスコープを使って実装してもらう必要があるということになります。
じゃあ次に3問目にいきます。これは時事問題ということで、私が最近X上で何回かつぶやいていた内容になるんですが、いきます。
Eloquent Builderの機能に関して、間違った説明をしているものはどれでしょう?
1番。createOrFirst()というメソッドは、まずINSERTしてみて、ユニークキー制約エラーになった時だけSELECTするという動きをする。2番。firstOrNew()は、まずSELECTしてみて、結果があればそれをインスタンス化、なければ空のPHPのオブジェクトでそのままモデルクラスをNEWするという動きをする。3番。firstOrCreate()は、まずSELECTしてみて、結果が見つからなかった時だけINSERTする。4番。updateOrCreate()は、まずUPDATEしてみて空振りした時だけ、要するにそのアップデートが走らなかった時だけINSERTする。
1つだけ間違っているものがあります。どれでしょうか。
発表にいきます。正解は4番です。updateOrCreate()が間違っています。updateOrCreate()は、最初にupdateという名前から始まっていますが、まずはSELECTクエリが投げられます。SELECTした結果があったら、それを基にUPDATEという処理が走って、なければINSERTされます。だから実際の動きはfirstOrCreate()みたいな名前が妥当というわけですが、省略したような名前になっていますね。
1番のcreateOrFirst()は聞き慣れない方がいるかもしれないですが、Laravel 10xで追加された機能になります。確かLaravel 10.20ぐらいだったかな? わりと最近の機能です。
これは宣伝になるんですが、createOrFirst()に加えて、firstOrCreate()とupdateOrCreate()に関しても以前は使われていなくて、シンプルにcreate()を使っていました。10.29以降は内部的にcreateOrFirst()を再利用するようになっていて、これによって、並列実行された時、例えばレプリケーション遅延とかが起こっていたとしても、安全なフォールバック動作を取ってくれるようになっています。
ということで、firstOrCreate()、updateOrCreate()の実用性が、10.29以降は以前よりも上がっていると思ってもらってかまいません。
では4問目にいきます。タスクスケジューリング機能に関して、間違った説明をしているものはどれでしょう。
1番。withoutOverlapping()とonOneServer()という機能がどっちもあるんですが、ともにタスクの重複実行を防ぐための機能である。2番。バッチサーバーが複数台構成の場合、必ずしもこれらを両方使わなければならないとは限らない。どっちかだけで十分ということですね。3番。複数台構成の場合、これらを使うためには必ずキャッシュドライバとして、ファイルじゃなくて、RedisとかMemcachedといったKVSを使用しなければならない。4番。withoutOverlapping()は単一台構成の場合に使っても意味がある。
タスクスケジューリング機能は使っていない方もいるかもしれないですが、ご了承ください。どれでしょうか。
正解は3番ですね。複数台構成の場合、これらを使うためには必ずキャッシュドライバとしてKVSを使用しなければならない。実用上、KVSを使うことがほとんどですが、これは引っかけ問題で、実はKVSを用意せずともリレーショナルデータベース、MySQLとかPostgreSQLを使ってもらってOKです。
ローカルファイルを使うと、そのインスタンス内だけでしか共有されないんですが、共有されるものを選べばなんでもいいので。KVSじゃなくてRDBでもOKという引っかけ問題ですね。
このあたりに関しては、以前のQiitaの記事で説明させてもらっています。
(スライドを示して?)このあたりは補足ですが、時間がないので端折ります。
5問目。テストで使用できるトレイトについて、間違った説明をしているものはどれ?
1番。DatabaseMigrationsはテストメソッド開始ごとに毎回全テーブルをDROPして作り直しを行う。2番。DatabaseTransactionsはテストメソッド開始ごとにトランザクションを開始し、テストメソッド終了時にロールバックを行う。3番。DatabaseTruncationはテスト全体で1回だけ、全テーブルの全行削除を行う。4番。RefreshDatabaseはテスト全体で1回だけ、テーブルのDROPと作り直しを行う。
どれでしょうか。この中でたぶん一番有名なのがRefreshDatabaseだと思いますが、それ以外にもたくさん存在しています。
では正解にいきます。間違っているものはどれでしょう。3番です。DatabaseTruncationはテストメソッド開始ごとが正解になります。DatabaseTransactionsとかRefreshDatabaseのようにテスト用トランザクションが生えないので、比較的実操作に近いテストが可能です。
ということで、個人的にはこれはRefreshDatabaseよりも今はDatabaseTransactionsを使ったほうがいいんじゃないかなというぐらいで、わりと推しているトレイトになります。
(スライドを示して)一応他の説明も書いてあります。もうあと1分しかないので飛ばしていきます。
6問目。UUIDについて間違った説明をしているものはどれでしょう。
1番。Strクラスのuuid()というメソッドはデフォルトでUUID v4を返す。2番。orderedUuid()はUUID標準に準拠していない。3番。uuid()もしくはorderedUuid()というメソッドはそれぞれ別々にロジックをカスタムすることができる。4番。orderedUuid()は、2059年問題みたいな生成スペース枯渇に関する問題を抱えている。
1つだけ間違った説明があります。
では正解にいきますかね。これが最後の問題です。3番です。uuid()、orderedUuid()のロジックをそれぞれ別にカスタムすることはできません。非常に残念な実装になっているんですが、createUuidsUsing()というメソッドで、どちらもここで設定したクロージャ―を使うような動きになってしまいます。非常に残念な実装です。なぜそうなっているかは私にもわかりません。
uuid()に関してはデフォルトのUUID v4が返ってきますね。orderedUuid()はLaravelがオレオレで用意したものであって、UUID標準は無視しています。
2059年問題があるということに関しても正しいです。なので、長期的に動作をするソフトウェアを作る場合はorderedUuid()は使わずに、整列されているUUIDで良ければUUID v7というものを自分で用意したほうがいいかなと考えています。
ちょうど時間になったので、これで終わりにします。
関連タグ:
2024.12.20
日本の約10倍がん患者が殺到し、病院はキャパオーバー ジャパンハートが描く医療の未来と、カンボジアに新病院を作る理由
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.17
面接で「後輩を指導できなさそう」と思われる人の伝え方 歳を重ねるほど重視される経験の「ノウハウ化」
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05