Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
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
640
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
370
どうして手を動かすよりもチーム内のコードレビューを優先するべきなのか
okashoi
3
1.5k
パスワードのハッシュ、ソルトってなに? - What is hash and salt for password?
okashoi
3
230
設計の考え方 - インターフェースと腐敗防止層編 #phpconfuk / Interface and Anti Corruption Layer
okashoi
11
4.1k
"config" ってなんだ? / What is "config"?
okashoi
0
1.3k
ファイル先頭の use の意味、説明できますか? 〜PHP の namespace と autoloading の関係を正しく理解しよう〜 / namespace and autoloading in php
okashoi
4
1.7k
MySQL のインデックスの種類をおさらいしよう! / overviewing indexes in MySQL
okashoi
0
950
【PHPカンファレンス沖縄 2023】素朴で考慮漏れのある PHP コードをテストコードとともに補強していく(ライブコーディング補足資料) / #phpcon_okinawa 2023 livecoding supplementary material
okashoi
3
2k
その説明、コードコメントに書く?コミットメッセージに書く? プルリクエストに書く? - #phpconfuk 2023
okashoi
16
5.4k
Other Decks in Programming
See All in Programming
実践!App Intents対応
yuukiw00w
1
290
オープンセミナー2025@広島「君はどこで動かすか?」アンケート結果
satoshi256kbyte
0
110
フロントエンドのmonorepo化と責務分離のリアーキテクト
kajitack
2
120
Google I/O Extended Incheon 2025 ~ What's new in Android development tools
pluu
1
290
Honoアップデート 2025年夏
yusukebe
1
770
JetBrainsのAI機能の紹介 #jjug
yusuke
0
210
技術的負債で信頼性が限界だったWordPress運用をShifterで完全復活させた話
rvirus0817
1
1.9k
書き捨てではなく継続開発可能なコードをAIコーディングエージェントで書くために意識していること
shuyakinjo
1
290
マイコンでもRustのtestがしたい その2/KernelVM Tokyo 18
tnishinaga
2
2.3k
DockerからECSへ 〜 AWSの海に出る前に知っておきたいこと 〜
ota1022
5
1.6k
サイトを作ったらNFCタグキーホルダーを爆速で作れ!
yuukis
0
370
LLMOpsのパフォーマンスを支える技術と現場で実践した改善
po3rin
8
950
Featured
See All Featured
StorybookのUI Testing Handbookを読んだ
zakiyama
30
6k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
26k
Bash Introduction
62gerente
614
210k
Navigating Team Friction
lara
188
15k
The Invisible Side of Design
smashingmag
301
51k
Done Done
chrislema
185
16k
The Pragmatic Product Professional
lauravandoore
36
6.8k
Documentation Writing (for coders)
carmenintech
73
5k
jQuery: Nuts, Bolts and Bling
dougneiner
64
7.9k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
161
15k
Stop Working from a Prison Cell
hatefulcrawdad
271
21k
YesSQL, Process and Tooling at Scale
rocio
173
14k
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 のランタイムそのものを安 全にしてくれるわけではないので注意