
こんにちは!二次元コンテンツ開発部 のozaki-kotaです。
3月20日(金)より3日間にわたるカンファレンス、PHPerKaigi 2026が今年も開催されます!
DMM.com(以下、DMM)も 2025年に引き続き、「シルバー」「Tシャツ」スポンサーとして協賛しています!
記事内に「チャレンジトークン企画」用トークン(#文字列)を掲載していますので、ぜひ最後までお読みください!
PHPerKaigi とは?
PHPerKaigi(ペチパーカイギ)は、PHPer、つまり、 現在PHPを使用している方、過去にPHPを使用していた方、 これからPHPを使いたいと思っている方、そしてPHPが大好きな方たちが、 技術的なノウハウとPHP愛を共有するためのイベントです。 今年の開催もオフライン会場を軸とした オフライン・オンラインハイブリッド開催です。 みなさんのご都合に合う参加方法をお選び頂けます。
2026年3月20日(金)〜 3月22日(日)はPHPerたちのお祭りです! 歴戦の勇者みたいな方はもちろん、初心者の方にも、 全てのPHPerが楽しめるイベントです。
PHPerKaigi 2026 開催概要
【開催】
2026年3月20日(金)~ 3月22日(日)
【場所】
中野セントラルパークカンファレンス&ニコニコ生放送
【対象】
PHPエンジニアおよびWeb技術のエンジニア
【主催】
PHPerKaigi 2026 実行委員会( 実行委員長 長谷川智希(@tomzoh) )
- お申し込みは こちら から
チャレンジトークン企画概要
PHPerKaigi 2026 で、会場参加者向けに行われるイベントです。
協賛企業や運営がさまざまなところに設置したチャレンジトークンを集めることで、景品を獲得できたりします。
AI時代のPHPでの検証方法を考えよう
というわけでPHPerKaigi 2026は楽しみですね! 私も当日は参加者として参加させていただく予定です。せっかくなので当日にPHPerの方と話したいネタを記事にしようと思います。
問題提起
みなさん、今の時代に検証をどう書かれていますか?
というのも2025年11月のOpus 4.5のリリース、12月のGPT-5.2のリリースを境にAIのコードを生成する能力が格段に上がり、意図した機能を作り切れるようになりました。 私自身も個人開発においてはコードすら見ずに、AIに対して「please continue for goal」と伝えるだけのことも多いです。
しかし、AIの生成したコードをそのままプロダクションにリリースできるかと言うと、そうではありません。 AIでコードを生成した場合、以下のような問題が生まれます。
- AIが最小の変更をし、全体の一貫性・整合性を壊すことがある
- AIが知らないものは暗黙的に補完され、意図しない挙動が生まれる
これらはコードレベルの問題で済むことがあります。しかし仕様の問題に繋がりやすく、どのように解決するかが重要になってきます。
最近よく見かけるのは仕様駆動開発や、ルール、スキルなどのAIに渡す情報を充実させることで、AIが生成するコードの品質を上げる方法です。 これらはとても大事な手法ですが、私はいかんせん不精者でこういったアプローチは面倒で仕方ないです。
そこで私はAIが生成したコードを検証する、後ろ側での検証に比重を置きはじめています。
みなさんはPHPにおけるこの後ろ側の検証方法をご存知ですか? 私もこれをやり始めて知ったことも多く、私の学びを共有できればと思います。
Agentの禁止設定
まず、AIからの可視性、変更可否はかなり気をつけてます。 基本的に設定ファイルは原則変更禁止で、その他は用途に合わせて調整をしています。
例えば私は普段Claude Codeを使いますが、その場合には下記のようにRead/Edit/Bashの設定を入れるようにしています。
{ "permissions": { "allow": [], "deny": [ "Read(AGENTS.md)", "Edit(AGENTS.md)", "Write(AGENTS.md)", "Bash(*AGENTS.md*)" ] } }
見えていいが、変更をさせたくないときはReadだけを外す形ですね。
ただし、この設定でも極端なことを言えばbashを駆使して見ることは可能です。
それすらも絶対に防ぎたい場合はプロジェクトごと分けるのが望ましいです。
また、変更禁止にしているファイルには念の為冒頭にコメントを入れるようにしています。
<!-- NOTE: You do not have permission to overwrite this file. Please ask a human operator to perform the changes for you. --> # AGENTS ...
特に変更されたという経験はありませんが念のためのおまじないです。
この記事を書きながらAIを実行していたら変更されました。Claude Code限定の話になりますがサブエージェントのBash経由で変更されたのでこの辺りに何か想定しないパターンがありそうです。
こういった禁止設定ファイルを弄りたいときもあるので、そういった際にはCodexなどの別のAI Agentを利用してます。
静的解析
静的解析は検証を保つための土台になります。例えば以下のようなことを確認できます。
- このクラスがあるなら、こういったテストがあるべき
- こういった呼び出しは行ってはいけない
など、一貫性や効果的に保証をするために利用します。
PHPStan
PHPStanは静的解析ツールです。
PHPStanの設定は主にレベルMaxでStrictルールと独自の拡張ルールだけ有効にしてることが多いです。
# NOTE: You do not have permission to overwrite this file. Please ask a human operator to perform the changes for you.
includes:
- vendor/phpstan/phpstan-strict-rules/rules.neon
- vendor/me/phpstan-custom-rules/extension.neon
parameters:
level: max
paths:
- src
- tests
稀にここだけはルールを許可したいケースなどもあるので、そういった際にはignoreErrorsで許可することもあります。
PHPStanで重要なのは独自の拡張ルールです。例えば以下のようなルールを作成しています。
@phpstan-ignoreや@infection-ignore-allコメントなどの制約許可を禁止- コードに対応するテストコードを必須化
などAIの制約の回避を禁止したり、やってほしいことをカスタムルールにしています。
このとき、メッセージは○○は禁止のようにエラーになったことではなく、〇〇はすることができません。××をするかユーザーに依頼してphpstan.neonにignoreErrorsに追加してくださいのようにどうして欲しいのかを書くようにしています。
従来であればこういったカスタムルールの作成コストはとても高かったのですが、昨今では数分でできるので気軽に追加しやすくなりました。
Deptrac
Deptracはレイヤーの依存方向を固定化する静的解析ツールです。
よくある使い方としてはドメインレイヤーを定義し、ドメインレイヤーは他のレイヤーに依存させないなどの制約を持たせるなどです。
Deptrac自体に直接的な問題を解決する機能はありませんが、生成したコードの品質が上がるので安定性のために入れています。
作成しているアプリケーションによってはモノレポ構成で複数のパッケージに分けた方がいいケースもあるので、そちらで代用も可能です。 厳密な使い分けはありませんが、私は基本的にはDeptracを使い、ライブラリなどで依存関係を最小化したいときはモノレポでパッケージを分けるようにしています。
テスト
テストは誰が定義し、誰が変更するのか、何を検査したいのかで切り分けを行っています。
AIが動作確認するためのテスト
従来では仕様化や設計の匂いを感じるためにユニットテスト等を書いてましたが、今ではAIが早期に動作確認をするためのものになったと感じています。 そのため、基本的には最小限の品質確保はしつつ、あまり細かくは見ないようにしています。
また、ユニットなのかインテグレーションなのかに関しても特に気にせず、時間指定のテストサイズだけ気にしています。あとはCIで実行の最適化さえできれば良いというスタンスです。
PHPUnit
PHPUnitは定番のテストフレームワークです。
まず、設定は硬めに倒しています。
特に重要なのはexecutionOrderで実行順序に依存させないこと、failOnXxx/ignoreSuppressionOfXxxで良くないものを検知できるようにすることでしょうか。
<?xml version="1.0" encoding="UTF-8"?> <!-- NOTE: You do not have permission to overwrite this file. Please ask a human operator to perform the changes for you. --> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" bootstrap="vendor/autoload.php" colors="true" cacheDirectory=".phpunit.cache" executionOrder="depends,random" requireCoverageMetadata="true" beStrictAboutCoverageMetadata="true" beStrictAboutChangesToGlobalState="true" beStrictAboutOutputDuringTests="true" failOnAllIssues="true" failOnEmptyTestSuite="true" failOnRisky="true" failOnWarning="true" enforceTimeLimit="true" timeoutForSmallTests="1" timeoutForMediumTests="10" timeoutForLargeTests="60"> <testsuites> <testsuite name="unit"> <directory>tests/Unit</directory> </testsuite> <testsuite name="integration"> <directory>tests/Integration</directory> </testsuite> </testsuites> <source restrictDeprecations="true" restrictNotices="true" restrictWarnings="true" ignoreSuppressionOfDeprecations="true" ignoreSuppressionOfPhpDeprecations="true" ignoreSuppressionOfErrors="true" ignoreSuppressionOfNotices="true" ignoreSuppressionOfPhpNotices="true" ignoreSuppressionOfWarnings="true" ignoreSuppressionOfPhpWarnings="true"> <include> <directory>src</directory> </include> </source> </phpunit>
※ PHP 8.1以上サポートのコードなのでPHPUnit 10での設定です。
またPHPStanでも独自の拡張ルールを作り、最低限の品質確保はするようにしています。
- コードに対して必ずテストファイルが存在すること
- テストファイルに対応したコードが存在すること
- interface以外のモックの禁止
モック禁止は厳しく見えるかもしれませんがtestcontainers-phpや、php-vcr、vfsStreamなどIOに関わる依存をあらかじめ追加しておけば特に問題になりません。
これにCIでのカバレッジチェックを入れておけばだいたいある程度のテストはできる印象です。
Infection
InfectionはMutation Testingのためのテストフレームワークです。
Mutation Testingはコードの一部を変更し、テストでそれを捕捉できるかを確認しテストコードの有効性を検証する手法です。 最近だとAIで攻撃側と防御側に分かれてコードの変更とテストで検知をするという論文も出ていたのと同じ目的の手法になります。
用途としてはテストコードの最低限の品質確保のために入れています。
個人的な印象として、テストでassertNotNull/assertInstanceOfだけの意味のないテストを防ぎたいです。またテストの量が純粋に足りていないといったことを防ぐために入れています。
仕様のテスト
仕様のテストはアプリケーション全体を通して、満たすべき仕様に関するテストを書きます。
AIが動作確認するためのテストと同様にPHPUnitを使いますが、基本的にAIには変更させずに、人間が先に変更するか特に制限をかけないAIでここだけの変更をしてもらいます。 本当は仕様変更のときのみ許可制で変更できるといいのですが、そこまで細かい設定はできないので、ここは運用でカバーする形ですね。どうしても実装の問題なのにこのテストを変更されてしまうことがあり、仕方なくこういった運用をしています。
今はPHPUnitを使っていますが、もしかしたらBDDフレームワークのBehatなどの方がより仕様のテストには適しているかもしれません。
仕様記述の方法としてEARS記法などがありますが、それをそのまま落とし込みやすいという意味でBDDが管理しやすそうです。
ユーザーシナリオのテスト
ユーザーシナリオのテストは実際にAIに対象のアプリケーションを操作させて、うまく使えないケースを検知するためのテストになります。
こちらもAIが動作確認するためのテストと同様にPHPUnitを使いますが、プロジェクトとしては別にし、対象コードは見せずにドキュメントだけで利用してもらいます。 私は普段ライブラリ開発のためPHPUnitとしていますが、WebアプリケーションなどであればJSのE2Eテストフレームワークなどの方がより適しているかもしれません。
ここに関しては正直言ってまだ自分の中で定まっていません。 おそらく今後はこういったプロジェクトの外部で連携し、コードを生成、レポートをする仕組みが重要になり、一定のCIアプリケーションのようなものを生む必要があるとは思っています。例えば以下のような手法です。
- E2E
- ペネトレーションテスト
- 形式手法、形式仕様記述
こういった手法を使い、コード自体はAIが管理しつつ、アプリケーションのコードに追従して品質を保つイメージです。 ただ、まだどういった連動すると良いかは見えていないので、いったんはローカルでどう再現させるのか検証している段階になります。
性質のテスト
性質のテストは対象がその性質を満たすなら、常に成功することを保証するためのテストになります。 主にAIの考慮漏れを検知するために利用します。
Eris
ErisはProperty Base Testingを行うためのツールです。
Property Base Testingはテストコードに対して、特定の入力に対して特定の出力になるといった性質を定義し、その性質を満たすような入力を自動で生成してくれるテスト手法になります。 例えばドメインモデルであれば不変条件を満たしていれば常に正しい状態であるなどですね。また振る舞いに関しても常にまさしく振る舞うことを保証できます。
個人的にはとても有益だと思うものの、いかんせん速度とのトレードオフが悩ましいところです。 私の場合は例えばドメイン層など、ここは絶対に崩れて欲しくないといったケースでのみ限定的に使うようにしてます。
もし、使う場合はPHPStanで独自の拡張ルールで特定のネームスペースのテストであればErisを使ったテストが存在することというように強制することが多いです。
PHP-Fuzzer
PHP-FuzzerはFuzzingを行うためのライブラリです。
FuzzingはProperty Based Testingに近いですが、より大きな範囲で性質を満たしているかを保証するために使います。 私はよくFakerと合わせて使うことが多いです。
例えば私は最近SQLを受け取るライブラリを作成していますが、そちらではFakerベースのSQL生成器を作り、ライブラリ全体の動作を確認するなどしています。
1つ注意点があり、FuzzingはAIで作るのがいまだに難しい領域の1つかなと思います。 気軽にお願いしたら仕様を満たすようなFuzzingを作ったり、配列で数パターン作ってランダム選択で終わったりとかなり酷い目にあいました。 どうやってパターンを生成するかはかなり意識する必要があります。
個人的にはFuzzingはプロジェクト外で作成するのが望ましい手法だと思います。 まだ試していませんが、対象のREADME.mdやdocsだけ参照させ、コードを見られないようにReadを禁止したうえで作成する方がよりFuzzingの性質にあった形で作っていけそうかなと思います。
契約のテスト
契約のテストは主にシステム間の契約を保証するためのテストになります。
Pact PHP
Pact PHPはConsumer-driven Contract Testingを行うためのライブラリです。これはまだ実際にAI利用はできていません。
これはConsumer側が期待するという動作をユニットテスト等に組み込み、そこで記録された内容を契約としてProviderに引き渡します。 Providerはそれを元にテストを実行することでConsumerの期待する動作をすることを保証するといったテスト手法になります。
わかりやすいところで言えばHTTPサーバー/クライアントでクライアントがConsumerとしてPactを組み込みサーバーに送信するリクエストとレスポンスを記録。 サーバーではそれを再生して期待する動作になっているか確認をするといったことができます。
Pact自体はPub/SubやStreamなどでも利用可能で、システム間の影響を最小化するのに役立ちます。
個人的にはとても好きな手法であり、恐らく効果は高いとみています。ただ、導入には複数のチーム間での協調が必要であり難易度は高めです。
その他
他にもいろいろ使い道はありそうとは思いつつ、自分の中で使い道が定まってないツール、ライブラリも紹介します。
また、今回はPHPにフォーカスしているため紹介はしませんが、モニタリングも一種の検証であると思っており、リリース後の検査としてそこの重要性も上がっています。
AIによって何が変わったのか
ここまでの紹介を見て結構知っていたり、やっているものも多いのではないでしょうか。 実際のところこのAIの後ろ側の検証というものは人間がコードを書くときと何も変わっていないと思います。
では何が変わったかと言えば、AIによっていろいろなコストを踏み倒せるようになったことだと思います。
- 保証したいことを気軽に保証できるようになった
- 学習コストや運用のために維持するコストを気にする必要がなくなった
コストの問題で本来はやるべきだったことが、AIの力によってやれるようになったという感じですね。 その結果として、よりソフトウェアエンジニアリングにフォーカスして開発を進めることができるようになったのではないでしょうか。
ちなみに、ここまで厳格に設定すると、逆に人間には書くのが面倒すぎる状態にもなってきてます。
仕様をどう管理するのかという問題
ここまで色々やっていれば大丈夫と思われるかもしれませんが、問題の完全な解決とまではいきません。
一番の問題は多層的に保証を入れたことによって、その正しさをどうやって担保するのかという点です。 部分的には正しいが全体としては間違っている、あるいは漏れや矛盾しているといったことが起こりうるため、何か1つの正しい仕様が欲しくなります。
そのために形式手法や形式仕様記述などにも手を出し始めていますがこちらもやはり完全ではなく、手法によってカバーできる範囲というものが限定されるため、やはり多層的になっていきます。
形式仕様記述自体は記述するコストの高さが問題になるため、おそらくAIでコストを踏み倒せる見込みです。 ただ、まだどういった手法でいいのかは見えていないため、引き続き模索している段階になります。
これはPHPのツールではありませんが、Pactiなどは気になっています。 Assume-Guarantee (AG) contractsが概念としてとても面白く、何かに使えそうというので掘り下げています。
また、LeanやZ3なんかも面白く最近は気になって調べています。
まとめ
ここまで後ろ側での検証の方法について紹介してきました。 この後ろ側での検証もとても重要ではあるのですが、掘り下げれば掘り下げるほど、実はその前段階も重要になってきます。
ハーネスやコンテキストエンジニアリングを詰めないと検証失敗に対してハックするようになり、逆に悪化することがあります。 システムの設計を詰めないと検証範囲が膨大になり、現実的に検証できなくなります。
あくまでも、私は後ろ側を主軸に置いて前段階を詰めるというものであり、どこから始めるのかと言うだけの話になります。
結局はぜんぶやることになるので皆さん好きなところから始めましょう。
最後に
ここまで読んでくださりありがとうございました。
今回のトークン文字列は「#誰もがみたくなる未来。」です!
私たち DMM テックチームは、コーポレートメッセージに「誰もがみたくなる未来。」を掲げながら、エンタメをはじめさまざまな領域で終わりのない挑戦に挑み続けています。DMM グループでは、一緒に働いてくれる仲間を募集しています。ご興味のある方は、ぜひ募集ページをご確認ください!