Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PHP における静的解析(あるいはそもそも静的解析とは) / #phpcondo_yasai ...
Search
Shohei Okada
January 11, 2024
Programming
1
960
PHP における静的解析(あるいはそもそも静的解析とは) / #phpcondo_yasai static analysis for PHP
2024/01/11 開催「PHPカンファレンス北海道2024 全然野菜」(
https://connpass.com/event/298365/
)の発表資料です。
Shohei Okada
January 11, 2024
Tweet
Share
More Decks by Shohei Okada
See All by Shohei Okada
たった 1 枚の PHP ファイルで実装する MCP サーバ / MCP Server with Vanilla PHP
okashoi
1
620
どうして手を動かすよりもチーム内のコードレビューを優先するべきなのか
okashoi
2
1.8k
パスワードのハッシュ、ソルトってなに? - What is hash and salt for password?
okashoi
3
290
設計の考え方 - インターフェースと腐敗防止層編 #phpconfuk / Interface and Anti Corruption Layer
okashoi
11
5k
"config" ってなんだ? / What is "config"?
okashoi
0
1.5k
ファイル先頭の use の意味、説明できますか? 〜PHP の namespace と autoloading の関係を正しく理解しよう〜 / namespace and autoloading in php
okashoi
4
1.9k
MySQL のインデックスの種類をおさらいしよう! / overviewing indexes in MySQL
okashoi
0
1.1k
【PHPカンファレンス沖縄 2023】素朴で考慮漏れのある PHP コードをテストコードとともに補強していく(ライブコーディング補足資料) / #phpcon_okinawa 2023 livecoding supplementary material
okashoi
3
2.1k
その説明、コードコメントに書く?コミットメッセージに書く? プルリクエストに書く? - #phpconfuk 2023
okashoi
16
5.6k
Other Decks in Programming
See All in Programming
AIエージェントを活かすPM術 AI駆動開発の現場から
gyuta
0
430
新卒エンジニアのプルリクエスト with AI駆動
fukunaga2025
0
230
認証・認可の基本を学ぼう前編
kouyuume
0
250
Giselleで作るAI QAアシスタント 〜 Pull Requestレビューに継続的QAを
codenote
0
220
MAP, Jigsaw, Code Golf 振り返り会 by 関東Kaggler会|Jigsaw 15th Solution
hasibirok0
0
250
ハイパーメディア駆動アプリケーションとIslandアーキテクチャ: htmxによるWebアプリケーション開発と動的UIの局所的適用
nowaki28
0
430
tsgolintはいかにしてtypescript-goの非公開APIを呼び出しているのか
syumai
7
2.2k
WebRTC と Rust と8K 60fps
tnoho
2
2k
Rediscover the Console - SymfonyCon Amsterdam 2025
chalasr
2
170
Rubyで鍛える仕組み化プロヂュース力
muryoimpl
0
140
re:Invent 2025 のイケてるサービスを紹介する
maroon1st
0
130
バックエンドエンジニアによる Amebaブログ K8s 基盤への CronJobの導入・運用経験
sunabig
0
160
Featured
See All Featured
The Invisible Side of Design
smashingmag
302
51k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.2k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
122
21k
jQuery: Nuts, Bolts and Bling
dougneiner
65
8.3k
How to train your dragon (web standard)
notwaldorf
97
6.4k
GitHub's CSS Performance
jonrohan
1032
470k
Making the Leap to Tech Lead
cromwellryan
135
9.7k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
For a Future-Friendly Web
brad_frost
180
10k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
980
YesSQL, Process and Tooling at Scale
rocio
174
15k
KATA
mclloyd
PRO
33
15k
Transcript
PHP における静的解析 (あるいはそもそも静的解析とは) 2024-01-11 PHPカンファレンス北海道2024 全然野菜
なにかがおかしいコード <?php // ... if ($empty($hoge)) { // ... }
<?php // ... if (empty($hoge)) { // ... } たぶんこう書きたかったんやろなあ
実話です · 私が 1 年目のときに自分がつくったバグ · 実際には長いコードの一部であり、デバッグに半日かかった · エラーハンドリング等も不十分だったのもある ·
PHP 的には構文エラーではないので余計に気づきにくい · $empty という変数は定義可能であるため
PHP における静的解析 (あるいはそもそも静的解析とは) 2024-01-11 PHPカンファレンス北海道2024 全然野菜
「静的解析」とは プログラムを実行せずに行う解析のこと · 構文エラー検出 · コーディングスタイルチェック · 複雑性の検出 · 型のチェック
· etc. ...... c.f.)動的解析:自動テスト、プロファイリング etc. ......
PHP の静的解析ツール例 · php -l コマンド · PHPMD · PHP_CodeSniffer(phpcs)
· PHPStan · Psalm · Phan · (PhpStrom)
PHP の静的解析ツール例 · php -l コマンド · PHPMD · PHP_CodeSniffer(phpcs)
· PHPStan ←本日取り上げるのはこちら · Psalm · Phan · (PhpStrom)
PHPStan https://phpstan.org/ ぞうさん かわいいね
PHPStan で検出できるもの(一例) · 構文エラー · 未定義の変数/定数/関数/クラス/メソッド · 間接的に typo を検出できる
· 型の不整合 · エラーチェック漏れなど · 冗長なコード
Web ブラウザ上でおためしできます https://phpstan.org/try
Q. 何がおかしい? <?php $environment = $_ENV['APP_ENV']; if ($enviroment === 'production')
{ // ... } https://phpstan.org/try
A. 変数の typo <?php $environment = $_ENV['APP_ENV']; if ($enviroment ===
'production') { // ... } https://phpstan.org/try
<?php /** @var string $heystack */ if (strpos($heystack, 'a') ===
fasle) { // ... } https://phpstan.org/try Q. 何がおかしい?
<?php /** @var string $heystack */ if (strpos($heystack, 'a') ===
fasle) { // ... } https://phpstan.org/try A. Boolean リテラルの typo
<?php /** @var string $dsn */ $pdo = new PDO($dsn);
$statement = $pdo->prepare('SELECT * FROM users WHERE id = ?;'); $statement->executeStatement([1]); https://phpstan.org/try Q. 何がおかしい?
<?php /** @var string $dsn */ $pdo = new PDO($dsn);
$statement = $pdo->prepare('SELECT * FROM users WHERE id = ?;'); $statement->executeStatement([1]); https://phpstan.org/try A. 存在しないメソッド
<?php function getMonth(DateTimeImmutable $dt): int { return $dt->format('n'); } $now
= new DateTime(); echo getMonth($now); https://phpstan.org/try Q. 何がおかしい?
<?php function getMonth(DateTimeImmutable $dt): int { return $dt->format('n'); } $now
= new DateTime(); echo getMonth($now); https://phpstan.org/try A. 戻り値の型の不整合
<?php function getMonth(DateTimeImmutable $dt): int { return $dt->format('n'); } $now
= new DateTime(); echo getMonth($now); https://phpstan.org/try A. 引数の型の不整合
備考)PHP の DateTime と DateTimeImmutable <<interface>> DateTimeInterface DateTime DateTimeImmutable 互換性はない
<?php /** @var string $heystack */ $index = strpos($heystack, 'a');
echo substr($heystack, $index); https://phpstan.org/try Q. 何がおかしい?
https://phpstan.org/try <?php /** @var string $heystack */ $index = strpos($heystack,
'a'); echo substr($heystack, $index); A. 型の不整合(false チェック漏れ)
余談)PHPDoc と組み合わせてより高度な型情報を扱える 今回は割愛 <?php declare(strict_types = 1); class Person {
/** @var int<0, max> $age */ public int $age; } /** * @param non-empty-list<Person> $persons */ function findOldestPerson(array $persons): Person { $oldestPerson = $persons[0]; foreach ($persons as $person) { if ($person->age > $oldestPerson->age) { $oldestPerson = $person; } } return $oldestPerson; }
余談)PHPDoc と組み合わせてより高度な型情報を扱える 今回は割愛 <?php declare(strict_types = 1); class Person {
/** @var int<0, max> $age */ public int $age; } /** * @param non-empty-list<Person> $persons */ function findOldestPerson(array $persons): Person { $oldestPerson = $persons[0]; foreach ($persons as $person) { if ($person->age > $oldestPerson->age) { $oldestPerson = $person; } } return $oldestPerson; }
さて https://speakerdeck.com/twada/growing-reliable-code-phperkaigi-2022?slide=10
さて https://speakerdeck.com/twada/growing-reliable-code-phperkaigi-2022?slide=10 静的解析を実施するのは だいたいこのタイミング(たぶん)
冒頭のコードを PHPStan にかけると <?php // ... if ($empty($hoge)) { //
... }
冒頭のコードを PHPStan にかけると https://phpstan.org/r/45d617bb-1bc1-4e2a-a1e9-24b8deeefff9
冒頭のコードを PHPStan にかけると https://phpstan.org/r/45d617bb-1bc1-4e2a-a1e9-24b8deeefff9
つまり https://speakerdeck.com/twada/growing-reliable-code-phperkaigi-2022?slide=10 静的解析ツールを使っていれば 不具合の発見のタイミングを早め傷を小さく収められた (また、ツールによって瞬時に発見できた)
まとめ · 静的解析ツールを使うとテストコードを書く以外の方法で 潜在的な不具合(うっかりミス等)を発見できる · ツールを使いこなして生産性をあげよう · (発展)PHP における型を意識した設計、実装の幅を広げてくれ る
· あくまで外部ツールであり、PHP のランタイムそのものを安 全にしてくれるわけではないので注意