phpcon2025 聴講セッションまとめ

昨日参加したPHPカンファレンス2025(初参加)で聴講したセッションの資料を再度見返しながら、当日の疑問点とかをまとめたり調べてみたりします
要するに、自分の復習用スレッドです

articlesの方で書くか迷ったけど、最近scrapsばっか書いててこっちの方がつらつら書けて楽しいのでこっちに書くことにした
articlesの方でもなんか書くかもしれないですが

9:50に会場到着
オープニングの途中で入場

10:00~
(僕が探した限りだと現在インターネット上にはスライドが上がってなさそう)

JITの話が出てたけど、そういえばJITのことちゃんと自分で言語化できるほど身についてないなと思ったので調べてみる。

「JIT PHP」で調べて最初に出てきた記事がこの辺
「JIT」で調べるとこんな記事も出てくる

Just In Timeの略
無駄なく、必要なものを必要な分だけ作るやり方のこと

PHPはインタプリタ型の言語で、JIT導入以前は、アクセスが来るたびにソースコードを全部読み込みオペコード(opcode)に変換し、逐次実行し、実行が終了したらコードを全て破棄するという方法をとっていた。
OPcacheがこの変換後のオペコードをメモリに保存しておき、次のリクエストでも使う仕組み。
JITは、リクエストが来たらソースコードを全部読んでオペコードにするとこまで同じ。ただ、その後一気にネイティブコードに変換する。
もう一度同じ処理が呼ばれた時は、同じネイティブコードを直接実行するので、処理速度がめっちゃ速くなる。ネイティブコードをメモリに保存して使いまわしたりもできる

パイプ演算子が便利そうでテンション上がりました
シェルスクリプトっぽいことができるってこと、、?

franken phpのこと名前しか知らなかったけど、この機会に調べてみる〜
フランケンのゾウさん可愛い🐘

franken phpにはPHPのソースが埋め込まれていて、それによりPHPがインストールされていなくてもfranken phpだけでPHPファイルを実行できる、という仕組み。
franken php自体はGoで実装されていて、ビルドすると1つの実行ファイルが出来上がり、その実行ファイルとPHPファイルがあればPHPを実行できる、という仕組み。
一般的なPHP拡張機能も一通り入ってる
なので、Webサーバーとして使ったり、PHPが実行できるCLIツールとして使ったりできる

10:55~
スライド:

最近、仕事の案件で初めてLaravelを使い始めた(個人的に使ったことはあるけど仕事で使ったことはなかった)ので、Laravelの話だ!と思って軽率に選んだ。
結果、あんまりよく理解してなかったCollection型のことがちょっとわかったので良かったです

そもそも、yieldにジェネレータ関数って名前があったことを初めて知った
yieldは処理の途中で別の処理が差し込めるんだな〜くらいの理解しかしてなかった
公式Docsにはちゃんとジェネレータって書いてあるのに、ちゃんと読めていない、、

メモにNikita氏すげーって書いてあって何だっけ?って思ったけど、スライドのNikita氏偉業シリーズのことだった

yieldのことは知ってるけど、どういう時にyieldを使うと便利なのかがあまりピンと来ていない

CollectionとかLazyCollectionとか、もっとちゃんと調べて色々触ってみたい気持ち
ここでやると時間かかりすぎなので別でやりたいな

DeepWikiのことも知れた。この登壇で初めて聞きました

試しにrequest for phpのdeepwikiを開いてみた
システムアーキテクチャとかまで見れる
リクエストフローもある
これ見たら本当にそのrepoの概要がざっくりわかってしまうね

11:25~
スライド:

Result型というのを作って、それに成功時の結果も失敗時の結果も書いてreturnしちゃおうという話。
php8.5のattributeで使えるNoDiscardと合わせて使うとシナジーありそうだなと思いながら聞いてた

ビジネスエラーと技術的エラーでエラーハンドリングの仕方とか扱いを変えようっていうのに共感できた。
例えば、料金の入力をするフォームで、技術(この場合だとデータベースとかアプリケーションのバリデーション)的には整数が入力可能だけど、ビジネス的には100円を下回っちゃいけない、みたいなルールがあった時に、198.8円って入力された時と50円って入力された時のエラーハンドリングが同じでええんかっていう感じよね

僕はResult型とかじゃなくてExceptionを継承したオリジナル例外クラスみたいなのを作ってcacheするみたいなことをする派だけど、確かにこれだとどこでcacheされるか分からんっていうのはある
cacheが漏れててそのまま500を返しちゃうみたいな

ビジネスルールとかで「こういう時は失敗するよ」っていうのが明確にあるなら、それ用のResult型を作っちゃうのはアリかもと思いました

12:45~
スライド:
個人的に一番興味深かった

BDD、名前だけ聞いたことあって詳細は全然知らなかったので興味深く聞かせていただきました
TDDの発展形ってことも知らなかった

プログラムを書いてるとしばしば「この機能って何に使うんだっけ」とか「誰がどういう場面で使うんだっけ」みたいな視点がうっかり抜けがちなので、そうなる前に自然言語で要求仕様を書いてそれをプログラムのテストに落とし込めるのが良いな〜と思った

Given-When-Thenは覚えとくと良さそう

これでGit管理とかしちゃったら、認識の共有もしやすいし、定期的に見返したりできたら途中で認識が歪んだりもしにくくなりそう

13:15~
スライド:

案件でrachet使ったWebSocketの実装をやったけど、WebSocketも色々ライブラリあるからどれ使うのが正解だったのかな〜っていうのが知りたかったので、そのヒントになればと思って聞きました

ReactPHP、amphp、workerman、road runner、swooleあたりを一度調べてみるのが良さそう

コンテナならSwoole、レンサバならamphpが良さそうとのこと

13:50~
スライド:

BPaaS(Business Process as a Service)って初めて聞いた
ソフトウェアの提供ではなく、業務プロセスそのものを提供するクラウドサービスであり、クラウド経由で業務アウトソーシングが可能

14:20~
スライド:

何はともあれ、一旦property hooksの公式Docsを読みたい

仮想プロパティとバックドプロパティ
フックの中で自身で同名の実体を正確に参照してれば、バックドプロパティ

class User
{
public function __construct (
public DateTime $birthDate {
set(DateTimeInterfave|Stringable|string|Closure|int|float $value) {
// 省略
}
}
) {
}
}
// ok
$user = new User(new DateTime('2025-06-29'));
// ok
$user->birthDate = '2025-06-29';
// error
$user = new User('2025-06-29');
set()の引数の型だけ広がってて、コンストラクタの型はそのまま
class User
{
public function __construct (
public DateTime $birthDate {
// これはできない
set(string $value) {
// 省略
}
}
) {
}
}
→コンストラクタの型からset()の型に広げることはできる。狭めたり変更したりはできない

元々、僕の中でリスコフって「子ができることは全て親もできる必要があるし、親ができないことを子ができるようになってちゃいけない」くらいの解釈だったんだけど、より具体的にどういうことなのかが理解できた感じがする

14:55~の枠は、疲れて外を散歩してしまったので聞けませんでした、、
おかげでそれ以降の枠では集中力が復活したので良い判断だったとは思っている

15:25~
スライド:

実は、オンラインでTS kaigiに参加してて、その中でもプログラミングをするパンダさんの枠を聞いてたので、続きものと知りテンション上がってた

とりあえず読もうと思ってポチった本たち

mvcフレームワークから距離を置くのが流行ってるのはなぜ、、?

自分がクリーンなコードを書くのはもちろん、チームメンバーがみんな同じ形でクリーンなコードを書くのが大事。
そのために、全員で認識を合わせるための知識やらドキュメントやら共有の時間やらが大事だなぁと感じました

3つにレイヤーを分けて、4種類のオブジェクトと3種類のメソッドを使って、クリーンなコードを書く

16:00~
スライド:

そもそもRLSを知らなかったので、そんなのがあるんだ〜って感じだった
id | name |
---|---|
1 | テナントA |
2 | テナントB |
id | tenant_id | name |
---|---|---|
1 | 1 | 太郎 |
2 | 1 | 次郎 |
3 | 2 | 三郎 |
4 | 1 | 四郎 |
この時、tenant_idが1のデータ以外は無視するようにできるっていうイメージ。
無視というのは、selectもupdateもdeleteも同じ。
無視というか、見ようとするとエラーにするって感じ。0件ですじゃなくて、ちゃんとエラーが出る

この「見ようとするとエラーにする」というのが、
Eloquentの場合:例えばユーザーログイン時に触っていいテナントのIDを切り替えて、その後も最初に設定した状態で使い続けるイメージ
Doctrineの場合:このEntityManagerはテナントA、こっちはテナントB、みたいな感じで触れるテナントのIDを設定しておいて、どっちを触るかでEntityManagerを変えるイメージ
なので、Doctrineの方がEloquentと比べて明示的になるとのこと

16:35~のLTは、飛行機の時間の関係で聴けませんでした