なずなログ

ただのSIer系SEが思ったことや色々書く感じのアレです

2019年の振り返り

今年はいろいろ自分にとって初めてのことにチャレンジした年になりました。

参加したイベント

  • Laravel JP Conference 2019

    人生で2回目のカンファレンス参加になりました。
    一度目のカンファレンスよりも規模が大きく、はじめて懇親会に参加したカンファレンスでした。

    当時の私は社内でちやほやされているだけのエンジニアで、それとなくしか開発というものに取り組めてしかいませんでした。
    そんな中動向を知っておこうと思って参加してみれば、そこには開発を追及する人たちがたくさんいて、その方々の熱量、そして視点を初めて知って衝撃を受けた覚えがあります。
    ういろうさんまつぴーさんそーだいさんなど様々なきっかけをくれる人たちと出会うこともでき、私の中ではとても印象に残っているカンファレンスです。
    2020も参加します!

  • PHPerKaigi 2019

    ひたすらトークン集めに走り初日はいい感じの上位にいれたのですが、2日目は寝坊したことで上位争いから脱落しました。
    徳丸先生からの挑戦状という企画とセキュリティ関連のトークなどがあった影響でセキュリティに対しての関心が強まり、今では情報処理安全確保支援士取得に向けて勉強を進めています。 トークンを探し回る中、いろんな方とお話しさせていただいたのもいい思い出です。
    2020も参加させていただき、ルーキーズLT枠でお話しさせていただく予定です!
    Laravelで家電を操作してみよう by なずな | トーク | PHPerKaigi 2020

  • 大改修!劇的ビフォーアフター

    レガシーコードというか、クソコードを量産してきた私にとっては非常に刺さる内容ばかりでした。
    自分の関わっているプロダクトに対してもリファクタリングしたいと思いは以前からあったのですが、方向性だったり進め方だったり不安な中にいたので、プランを整理するきっかけにもなりました。
    新原さんのライブコーディングを見ていたらとてもPhpStormが欲しくなったのですが、ホビーユーザだしなあ…と思い悩んでいるところ。 はじめて吉田あひるさんにお会いして、フリー素材通りの方で安心しました。

  • PHP Conference 2019

    規模も歴史も今まで参加したカンファレンスの中で最も大きく、知っている方も多くいてワクワクして参加した覚えがあります。
    PHPerKaigiとかで頂いていた名札をもっていかなかったことは今でも後悔しています。 夜は終電逃すまで飲んでいたのであまり記憶にありません。。。

仕事について

上期と下期でやっている仕事ががらりと変わって色々苦労はしましたが、評価は上々でした。

上期では去年から引き続きオフショア開発チームのリーダーとしてわちゃわちゃやっていました。
人の育成、プロセスの改善、仕事の管理などマネジメント面で学ぶことは非常に大きかったと思います。
(残念ながら私が離れたのち色々な事情でそのチームは解散となりました……)

下期では新規案件のアプリ系を担当するチームのリーダーとなりましたが、ネットワーク等の基盤系、案件の進め方など今までとは違った知識が必要で、手間取っていました。
また、既存案件から離れてしまったのでリファクタリングなどやりづらい立場になりましたが、準備だけ進める分にはポジションは関係ないと思ってライブラリの整備などは進めています。

勉強について

8月上旬まで英語の勉強は基礎復習を進め、8月中旬からは情報処理安全確保支援士に集中して取り組んでいました。
結果として情報処理安全確保支援士は午後Ⅱが49点で脱落でした。
高度の集中力維持に不安があったため午後Ⅰ・Ⅱぶっ通しの過去問練習をメインにしましたが、理解度の低い箇所への対策が疎かになってしまったので、次はちゃんと受かれるよう対策していきたいと思います。
基本情報も応用情報も1回目が微妙なラインで落ちて2回目で合格という流れで来たので、今回もそのパターンに収められるようにしていこうかな。

英語の勉強は、オフショアチームを抜けたことであまり重要度は高くなくなってしまったのだけれど、いずれにせよ今後必要になる機会はあるので引き続き取り組んでいきたいです。

読書

マネジメントに思い悩んでいたのでその系統の本を漁っていました。詳細は割愛。
来年は技術書をもっと読んでいきたいと思います。

アウトプット

ブログは始めてみたものの、仕事の忙しさを理由に続けない日が続いてしまったことで断絶していました。
LTなどは全くなく、来年のPHPerKaigiで初めて勇気を出してやってみます。今年は元ネタをそろえ中…。

来年の抱負

  • LTとかアウトプットについてチャレンジいろいろやってみる
  • 知り得たことなどを出来るだけブログに書いてみる
  • 健康診断で再検査なし(今年はやらかしたので)
  • 自分の周りのものをリファクタリングする
  • 情報処理安全確保支援士合格する
  • 英語もそこそこ頑張る(参考書2冊は終わらせたい…)

「PHPカンファレンス2019」に行ってきました #phpcon #phpcon2019

どんなイベント?

今年で20回目となる、国内最大規模のPHPのテックカンファレンスです。
PHP Conference Japan 2019 - #phpcon
PHP Conference Japan - YouTube

セッション

PHP における並列処理と非同期処理入門(@m3m0r7)

PHP における並列処理と非同期処理入門 - Speaker Deck

  • 趣味はバイナリファイルを読むこと。
  • 並行処理 !== 並列処理
  • マルチスレッド !== マルチプロセス
  • PHPでの非同期処理 !== できない
  • 並行処理は小さいタスクに分割してそれぞれ処理するが割り込みが入るから順序保証はされない
  • 並列処理はコアにタスクを割り振っていき、並列処理の上に成り立っている。
  • スレッドはプロセスの一つであり、スレッドはプロセスではない。
  • 非同期処理はAの処理を実行中にBの処理を実行してもAの処理を止めない。実装は並列処理でも並行処理でも良い。
  • PHPで並列処理を実装するにはpcntlやpthreadsなどがある。
    • pcntlはプロセスフォーク
    • pthreadsはスレッドフォーク

Laravelにはジョブキューがあり、DBレコードを介して別プロセスで非同期処理を実現しているのでそれを使ったことはあるけれど、それ以外の非同期処理はやったことがなかったので参考になりました。
今のところ単一リクエスト内で非同期処理を行いたいケースが今のところないので、必要になったらまた詳しく調べたいと思います。

思想と理想の果てに -- クリーンアーキテクチャのWEBフレームワークを作ろう(@nrslib)

[PHP Conference 2019]思想と理想の果てに――クリーンアーキテクチャのWEBフレームワークを作ろう │ nrslib

  • 層は3つでも4つでもいい
  • Controllerはアプリケーションが求めるデータに入力を変換する。
    • ゲームのコントローラが電気信号で本体に入力データを送るのと同じ。
  • 処理(InputPort)や出力(OutputPort)にinterfaceを使うことで、差し替えることができるからモックを刺して主導権をビジネスロジック側に出来る。
  • 理想を追い求めると代償がある。
    • 現代のMVC2 WebフレームワークだとOutputPortを使わない。
    • 層の数に比例してclass/interfaceが多くなる。(めんどくさい)
  • 理想を守るためにフレームワークを作ろう(!?)
    • そのためにもスキャフォールディング機能を実現するライブラリを作る。
      • プログラムを作るためのプログラムを作るためのプログラム。
    • 思想が先。httpは後。
    • まず最初にMVCを捨てる。ControllerからViewをreturnしなくすることでClasicc MVCぽくする。
  • 情報はアウトプットする人のところに集まってくる。
    • my favorite 車輪
  • 10年前は早く開発できることが重要視していたけど、フレームワークは変わっていく。
  • 「誰にも思い描く夢がある、その思想・理想を是非とも実現してほしい」
  • 「思っていることがあるならやってみてほしい」
  • 「世界をひっくり返すのはだれでもできる」
  • 「次に世界をひっくりかえすのはみなさんです」

理想を追い求めるためのその熱量というものの凄さを垣間見ました。
一人で趣味でやっているのであれば理想を愚直に追い求めること自体は出来ますが、チーム開発だったりプロダクションだったりでは理想を追い求める代償が大きく、中途半端になって余計メンテしづらくなったり悲しい結果になるのだと思います。(今の現場でまれによく感じる)
それに対してプラグインだったり開発フレームワークだったりで「理想を追い求めた方が楽になる」という状況を作るのは有効なアプローチですよね。

5ヶ月でカバレッジを20%から90%にあげた話(@strtyuu)

5ヶ月でカバレッジを20%から90%にあげた話 - Speaker Deck

  • 注:カバレッジは必ずしも品質に比例するわけではない
  • 当時カバレッジ20%くらいのときに、存在しない未来の話で応募した。
  • 採択されて「やらなきゃ」と追い込まれ、3ヶ月で18%から90%にした。(すごい)
  • カバレッジを上げたかった理由
    • 気軽にコードを修正したい。
      • 依存が一方向だったら修正も楽だけど、循環すると難しい。
      • フレームワークレイヤを改善したいけど影響が大きいからテストをしっかりとしたい。
    • コードリーディングのコストを下げたい。
      • 10年も続いてれば歴史的経緯のあるコードがある。小さな後悔が大きな後悔になるには十分な時間。
      • 続けば続くほど関わる人が増えていくのでリーディングとかのコストに時間を払う人が多くなる。
      • そのコストを下げた方がエンジニアにとって幸せなのではないだろうか。
  • 進め方を決めてからやった。
    • エンドポイントに近い箇所からテストする。
      • エンドポイントに近いほど内部実装を気にせずに進められる。
      • カバレッジが稼ぎやすそうという動機も)
    • リファクタは最小限に。
      • 時間が足りないし、そもそもリファクタリングは継続して行うもの。
      • 完璧主義はダメ
    • にゃ~んクラスを妥協する。
      • にゃ~んクラス = いびつな形で妥協せざるを得なかったクラス。つらいときに「にゃ~ん」というところから命名した。
  • テスト環境を整備した。
    • 簡単にデータを作る仕組みを用意する。
      • 完全コンストラクタなクラスでもActiveRecordでもどちらでも対応できるようにしないとしんどい。
      • 状態に名前を付けてその状態を簡単に作れるようにしたい。
    • 簡単に結合テストできる仕組みを用意する。
    • テストの実行速度を早くする。
      • めちゃくちゃPRを出すので早くCIが回ってくれた方がうれしい。
      • pcovを採用。
    • グローバルヘルパをモック可能にする。
      • グローバルヘルパは挙動を変えることができない。
      • 「全部リファクタリングしてたら間に合うわけないじゃないですか」
      • PHP-VCRで乗っ取った。(非推奨)
  • 実際カバレッジを90%まであげてみて、それに見合った成果が出るかはわからない。
  • でもPHP7.4にあげてみたら手動テストでは見つからなそうなバグ/非互換を発見することができた。
  • カバレッジをあげることでリファクタリングをする土台が出来上がったので、ここからがスタート。

状態の抽象化ってテストするときには結構大事だと思っていて、状態の具体的なデータ状態に変更があった時にテストクラスへの影響が抑えられる仕掛けがあるとテストコードがちゃんとメンテされやすくなるのかなと思います。
カバレッジをあげるコストって後にならないと見合うかどうかはわからないので結構不安になるというか、他のことの方が優先度高いのでは…?って思うときはありますが、言語/パッケージのバージョンアップなど、欲しいときにカバレッジがちゃんとあるというのは心理的安全性的な意味合いでもコツコツ進めるべきなんでしょうね。
ちょっと自分がやろうとしているテスト環境の整備に対しての意欲を盛り上げていただきました。焼肉食べたいです。

「CPUとは何か」をPHPで考える(@tomzoh)

「CPUとは何か」をPHPで考える / What is a CPU? - Speaker Deck

  • 削った箇所の供養としてのマイクテストと映像テスト(前座)
  • CPUは「プログラム実行環境」「エミュレート対象」「電気回路」からの視点で見ることができる。
  • 「TD4」という4ビットCPUを題材にする。
  • 「プログラム実行環境」の視点で見ると、マシン語プログラムの実行環境であり、プログラムを実行してくれる存在。
    • 自分の使う機能のみの理解でOK
  • 「エミュレート対象」の視点で見ると、エミュレータのCPU部分であり、対象CPU用に書かれたすべてのプログラムを動作させる存在。
    • CPU仕様を完全に理解しなければならない。
  • 「電気回路」の視点で見ると、クロックに従って状態遷移する回路としてCPU命令を表現した存在。
    • 仕様と物理のパズルを読み解かなければならない。
    • プログラムカウンタは静的回路を処理装置化する存在。
  • CPU自作は面白いよ!

前座で論理回路の基礎理論を久々に思い出しました。懐かしい…。
CPUの基本原理は中々知る必要に迫られることはないけど、知ってみると面白いですね。
「プログラム実行環境」として見てみるとそんなに難しくないけれど、「電気回路」として見てみると途端に難しい存在になるんですよね、CPUって。
だけどCPU自作はちょっとハードル高い…。
久々にObnizとかArduino周りを触りたくなりました。

感想

会場についたら「ここまで人が多いものか」と予想よりも大きい規模にびっくりしました。
いろいろ聞きたいお話はありましたが、後日Youtubeで見させていただきます!(配信残ってるのありがたいです)

LT枠は上級者ぞろいでした…!
4分枠に変更となっていたにも関わらず、言いたいことを詰め込んで伝えきれるというのはすごいです。
言いたいことを最初の方に持ってくるというのは言い切れないことに対する保険として、自分がやるときは参考にさせていただきます 🙇

様々なスポンサー企業様の展示ブースではお菓子や飲み物だけではなくモバイルバッテリー、電子メモパッド、SIMケースまでいただいて「え…こんなにもらっていいの…?」と不安になるレベルで頂きましたが、ありがたく使わせていただきます!🙏

頂いたものリスト(順不同)

また、お声がけいただいた皆様、ありがとうございました!
テストだったり、DDDだったりと関心毎についてお話させていただけたので、参考になりました。
また来年のぺちこんでお会いしましょう!

「大改修!PHPレガシーコードビフォーアフター」に行ってきました

どんなイベント?

PHPer界隈のカンファレンスに参加したら一度はお世話になっているであろう「fortee」を題材に、PHPの匠による改善ビフォーアフターをお楽しみいただけるイベントです。

大改修!PHPレガシーコードビフォーアフター - connpass

セッション

メルカリ様セッション(@suzuki)

今回の会場はメルカリ様にご提供いただいており、更にドリンクまで提供いただきました!
森ビルは初で今後行くこともあまりないと思うので、レアな体験になりました…!
ありがとうございます!

Twitter検索

  • 価値を生み出しているレガシーコードを、「レジェンドコード」という。
  • namespaceを使っていなかったり、Fat Controller/Modelだったりと負債があった。
  • まずはテストがあったのでリファクタリングで対応していた。
  • リファクタリングだけでは辛くなってきたのでマイクロサービス化に舵を切った。
  • メルカリではマイクロサービスをテンプレート化することで簡単に立ち上げられるようになっている。

テストコードがあることの重要性っていうのがサービスが大規模になるにつれて効果を発揮していきますね。
テストコードがないと、「レジェンド」だからこそその生み出している価値を壊す可能性がある行為を取りづらくなってしまうので…。

独立したコアレイアパターンの適用(@shin1x1)

Twitter検索

独立したコアレイヤパターンの適用 - fortee 編 - / fortee-meets-independent-core-layer-pattern - Speaker Deck

  • Port&Adaptersは、USBのように刺さるものは何であっても大丈夫。
  • 極力FWに依存しないようにコアの部分を独立させる。
    • ただしFWに依存してもよいと自分で判断したなら依存させてもよい。(Carbonとか)
  • PhpStormを使ったライブコーディング
  • コントローラロジックをとりあえずそのままユースケースを切り出す。
  • まずはユースケースに必要なものは引数で受け取り、Httpレスポンスに必要なものは戻り値にする。
  • FWのExceptionは自分で定義しなおす。
  • TestCaseもFWで拡張している基底クラスではなく素のPHPUnitを使うことでFW依存させなくする。
  • Adapterはテスト用にテストコード内で無名クラスを作る方法もある。
  • 「0 or 100」ではなく、漸進的にリファクタリングする。
  • 適用する箇所を絞る。(副作用のある箇所だけなど)

PhpStormめちゃくちゃ便利そうで欲しくなりました。
単純なコンストラクタやGetterを作るのは人間のやる仕事じゃないというのはとてもわかりみが深いですね…。単純だけどミスりやすいっていうのもありますし。
PHP7.4のtyped propertyで会場が「おおーー!!」って盛り上がっていて面白かったです。

静的解析 (@tadsan)

Twitter検索

「PHPプロジェクトに静的解析を新規導入する」 #phperkaigi|tadsan|pixivFANBOX

  • 静的解析をすることでエラーとして顕在化していない「たまたま動いてるコード」の問題点を炙り出せる
  • PHPStanならCIで差分を見れる。
  • 「Phan Docker」で出てくるDockerImageは古いから使っちゃダメ。
  • baselineを一度取って、その後に「これ以上増やさないでくれ」ということができる。
  • issetの中などぱっと見エラーにならないところもある。
  • 地道なものを地道に潰していくのが大切。

静的解析はやらねば…と思ってるけどまだやっていない。
「たまたま動いてるコード」の問題点を炙り出せるというのは、静的コンパイルが出来ないPHPで安全性をなるべく高めるためには必要だろうなと思う。
baselineを一度取って、その後に「これ以上増やさないでくれ」と制約をつけるのはあとから導入するときに周りの理解は得られやすそう。

Vaddyによる脆弱性分析(@cakephper)

Twitter検索

  • VAddyでは脆弱性診断対象サイトを登録して、ユーザがproxyを使った状態で当該サイトを巡回(クロール)することでシナリオを作成する。
  • 自分で所有しているサイトのみ診断できる。海外ユーザがFacebookとかに診断かけようとしてるらしいけど、そういうのはNG。
  • パラメータ毎にXSSSQLインジェクションなどの検査を行う。
  • forteeでは1件の脆弱性が見つかった。(本番は修正済み)
  • ツールじゃ見つけにくい脆弱性(仕様なのか脆弱性なのか判断が必要なもの)もある。
    • 認可の不備
    • ログ出力不備
    • 複雑な攻撃経路
    • Mass Assignment
  • 長谷川さん「僕も素人じゃないんでね」

脆弱性解析は、そういうツールがあるのは知っていたけど実際の利用イメージがなかったので参考になりました。
結構機械的脆弱性検査って自分でやるにはコスパが悪く、結局試験項目としては上がらないものになりがち。
テストも人間が必要なところに関心を分離させて、ツールで見つけやすい脆弱性と見つけにくい脆弱性をそれぞれ分担を分けるのが良いんだろうなと思います。

レガシーなWebアプリケーションと向き合う(@blue_goheimochi)

Twitter検索

レガシーなWebアプリケーションと向き合う

  • レガシーソフトウェア改善ガイドによれば、レガシーと言っても種類がある。
    • レガシーコード
    • レガシー基盤
    • レガシーカルチャー
  • レガシーコードへの対応はいくつかある。
  • 「レガシーさ」には、計測できるものとできないものがある。
  • 計測できるレガシーさはコードの大きさや重複、循環的複雑度などがある。定量的に測れるのでアプリの健康診断的な感じ。
  • 計測できないレガシーさは、 // ここのコードは変更しないこと みたいなやつとか。
  • コピペコードは必ずしも悪ではないが、phpcpdなどで検知したら目視確認をして判断する。
  • 部分的にリファクタリングをしていく。一番重要なところを守るためにE2Eテストを書く。全部網羅するのはつらい。

コードの重複を検出したら、共通化していない理由とか他の人が判断できるようなコメントを書き残すとかがいいのかなと思いました。
コードを書いた人は「これは別の概念だからコードも別にして、重複してもやむなし」と考えていたのに、その思想が他の人に伝わらないと後で勝手にまとめられて事故ることも起きそうですよね。
コードの重複が可視化される弊害というか……。
ごへいもちさんはしずかなトーンで笑いを取っていくところがプロですね!

Forteeをバージョンアップしてみた(@yakitori009)

Twitter検索

Forteeをバージョンアップしてみた - Speaker Deck

  • 最初にバージョンアップ成功したか判断するためのユニットテスト/E2Eテストを作る。
  • E2Eテストはコストがかかる。作って維持する覚悟があるか。
  • まずはcomposer updateでマイナーバージョンを1つずつ上げていく→テストを動かす、というのを繰り返す。
  • 自動アップデートツールは必ずしも簡単にアップデートできるというわけではない。まれによく事故る。
  • PHPのバージョンアップの場合も同様にテストをしてアップデート結果を確認する。
  • PHP7.4からcompactに未定義変数を渡すとE_NOTICEが出るようになったが、実は静的解析ですでに検出されていた。
  • ランサーズのCM #採用やめよう で誤解されて採用しづらくなった。

滑らかなバージョンアップのためにはE2Eテストコードやらユニットテストやらないと確からしさは得られないから必要ですというのは再認識しました。
テストさえあれば一つずつ上げていけばどうにか出来るけど、テストがなければ上がったことの影響を一つ一つ手探りでやらなくちゃいけないのがつらいですよね…。(めちゃくちゃ心当たりがある)
compactってかなり事故起こりやすいですよね。
PHP7.4になって未定義変数の警告が出るようになったけど、それ以前は出なかったし、そもそも文字列で扱いにくいだとか……。

感想

最後の登壇者トークは、みなさんのトークスキルの高さが高く、参考になることがポンポンとでてきて面白かったです。

養殖物のコードよりも天然物のコード、例にするなら天然物の方が理解しやすいだとか、作ったからと言って無理して使い続ける必要はなくて、捨てるのも選択肢だとか。

次回開催の雰囲気もあったので、楽しみにしています!

余談

6階に喫煙所があると聞き、試しに特攻してみたのは私です。

一緒に行った方と「確か6階でしたよね?」「帰り18階って忘れないようにしないとですねー」みたいな話をしつつ、6階に到着。
降り立ってみれば左右にあからさまにロックがかかってそうなドアがあり、試しにドアノブをひねってみると開くようだった。
直感で「これ内側から開けられない扉なのでは?」と不安になり、同行してた他の方に一回ドアの外に出てもらい、外から開けられるか試したら開いたので安心してドアを通過した。

エレベーターホールから出てみると、右にはゲート。左にもゲート。道の先にはゲートしかなく、我々に進めない。
実は喫煙所に行くためにはビルカードが必要そうで、諦めて戻るかと思った矢先、さっきは開いたドアが開かない……。

さっき開いたのはドアを閉めてからロックされるまでの待機時間に被っていたらしく、エレベータも使えないため会場にも戻れないという詰んだ状態になったが、そこに救いの手を差し伸べてくださったのが警備員さんだった。

ちなみにエレベーターホールに戻れたとしても、エレベータ自体に認証機能があり戻れないのに変わりはなかったそうだ。 本当にありがとうございます🙏🙏

【Laravel】サブディレクトリで2サイト運用時に片方でしかログイン継続できない #Laravel相談ログ

友人からLaravel周りの相談を受けることが度々あるので、備忘録として残してみる。

相談内容

  • 2つのLaravelベースのサイトを作成している。

  • それぞれドキュメントルートのサブディレクトリとしてデプロイしている。

    [イメージ]

    • hogehoge/app1

    • hogehoge/app2

  • それぞれLaravel標準の認証機能を使っている。

  • 片方のサイトでログインした状態でもう片方のサイトにログインすると、先にログインしていた方がログアウトされる。

    [イメージ]

    1. app1にログイン
    2. app2にアクセス
    3. app2にログイン
    4. app1にアクセス ← ログアウトされてる!

聞かれたこと

なぜ発生するの?

⇒ ログイン情報をブラウザが保持するのにcookieを使っていて、同じcookie名だから後からログインしたサイトの方で上書きされる。

WEBサーバ(nginx)のせい?

⇒ No. Cookieを設定するのはあくまでアプリケーション。
Cookieはブラウザでドメイン単位で管理される。サブディレクトリ運用=同一ドメインなので、サブディレクトリのアプリそれぞれが同じ場所にCookieを保存する。
そのため、同名のCookieは衝突してしまい、後から更新したほうで上書きされてしまう。

解決方法

.envcookieプレフィックスを指定することでサイト間でセッションIDのcookieが同じキーで重複しないようにできる。

SESSION_COOKIE=app1

【Laravel】Blade記法のincludeとslotの違い

友人からLaravel周りの相談を受けることが度々あるので、備忘録として残してみる。

相談内容

Blade記法のincludeslotの違いって何?

includeとは

bladeテンプレートを読み込む方法。
@includeディレクティブを使用する。 一回作ったbladeテンプレートを再利用したいときに使う。
表示する内容を動的にするには、変数を使用する。

slotとは

includeと似ているが、変数だけじゃなくHTML自体を差し込みたいときに使う。
@componentディレクティブを使用する。

使い分け方

include

  • ページヘッダーやページフッターなど、固定のもの

  • 変数だけで済むような場合

slot

  • 途中にHTMLを差し込みたい場合

slotを使うと何がうれしいの?

HTMLをわざわざ変数に入れて渡す、という手間がいらなくなる。
また、HTMLを変数で渡してそのまま表示したいときには{!! !!}文を使用してエスケープをしないようにする必要性があるが、そんなことを気にする必要もなくなる。

【Laravel】普通のRequestを受け取った後にFormRequestに切り替える

やりたいこと

汎用的なRequestで一旦受け取って、あとからFormRequestを作成するようにすることで、無駄にコントローラやメソッドを生やさなくて済むようにしたい。 例えばAPIなどで、サービスが複数存在しているときに各パラメータを若干カスタマイズしたいときなどに使える。

routes/api.php
Route::post('/{serviceName}/apply', 'APIController@somethingAction')->name('apply');

解決方法

APIController.php
    /** @var array サービス名とバリデーションに使用するFormRequestの関連付け */
    protected $formRequests = [
        'hoge' => 'App\Http\Requests\HogeRequest',
        'huge' => 'App\Http\Requests\HugaRequest'
    ];

    /**
     * なんかのアクション
     * 
     * @param  Illuminate\Http\Request $request
     * @param  string $serviceName
     */
    public function somethingAction(Request $request, string $serviceName)
    {
        if (empty($serviceName) || isset($this->formRequests[$serviceName]))
        {
            // サービスを特定できない場合はNot Foundエラー
            abort(404);
        }
        
        // バリデーション実行のため、FormRequestを作成する
        $formRequest = app()->make($this->formRequests[$serviceName]);

        // do something
    }

参考にしたやつ Use form request manually · Issue #7995 · laravel/framework

解説

FormRequestをDIコンテナ経由で生成すると、自動的にvalidateが走るから。

/Illuminate/Foundation/Providers/FormRequestServiceProvider.php

Illuminate\Foundation\Providers\FormRequestServiceProvider
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->app->afterResolving(ValidatesWhenResolved::class, function ($resolved) {
            $resolved->validateResolved();
        });
        $this->app->resolving(FormRequest::class, function ($request, $app) {
            $request = FormRequest::createFrom($app['request'], $request);
            $request->setContainer($app)->setRedirector($app->make(Redirector::class));
        });
    }

大まかな流れはこんな感じ。

  • $this->app->afterResolving(ValidatesWhenResolved::class, function ($resolved){});で依存解決後の挙動を定義
  • Illuminate\Foundation\Http\FormRequestIlluminate\Contracts\Validation\ValidatesWhenResolvedをインターフェースとして実装しているため、FormRequestServiceProviderで定義されたとおりにvalidateResolvedが呼び出される
  • Illuminate\Validation\ValidatesWhenResolvedTraitvalidateResolvedメソッドでバリデーションを実行

そのため、インスタンスを生成するだけでバリデーションが実行される。

【docker】docker-compose PHP + MySQL + Nginxでnginxが`host not found in upstream`というエラーを吐いた時の対処法

やろうとしたこと

docker-compose.yml
version: '2'

services:
  web:
    image: nginx
    ports:
      - 8080:80
    volumes:
      - ./src:/src
      - ./web/default.conf:/etc/nginx/conf.d/default.conf
  app:
    depends_on:
      - db
    build: ./app
    volumes:
      - ./src:/src
    environment:
      MYSQL_USER: homestead
      MYSQL_PASSWORD: secret
  db:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: october
      MYSQL_USER: homestead
      MYSQL_PASSWORD: secret
    ports:
      - 13306:3306
    volumes:
      - ./db/mysql_init:/docker-entrypoint-initdb.d
      - ./db/mysql_data:/var/lib/mysql
    command: --innodb-use-native-aio=0

事象

Nginxがhost not found in upstream appというエラーを吐いてうまく起動しないで終了してしまう。

原因

appにdepends_on: dbが存在するから。 depends_onでappが起動待機中にnginxが起動するからエラーになる。 (要するに起動順序の指定が甘かった)

なお、depends_onはあくまで起動順序のみを見てくれるやつで、ちゃんと立ち上がったかどうかまでは確認してくれない。

解決方法

暫定対処

depends_onを消す(起動順は気にせずに、たぶん起動するだろう論)

本格対処

dockerizeを使用してコンテナの起動確認をしてからentrypointを叩くようにする。 dockerizeは以下の記事が詳しい。 dockerize を使って他のコンテナ内サービス起動を待つ