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
620
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
330
どうして手を動かすよりもチーム内のコードレビューを優先するべきなのか
okashoi
3
1.4k
パスワードのハッシュ、ソルトってなに? - What is hash and salt for password?
okashoi
3
210
設計の考え方 - インターフェースと腐敗防止層編 #phpconfuk / Interface and Anti Corruption Layer
okashoi
11
3.9k
"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
920
【PHPカンファレンス沖縄 2023】素朴で考慮漏れのある PHP コードをテストコードとともに補強していく(ライブコーディング補足資料) / #phpcon_okinawa 2023 livecoding supplementary material
okashoi
3
1.9k
その説明、コードコメントに書く?コミットメッセージに書く? プルリクエストに書く? - #phpconfuk 2023
okashoi
16
5.4k
Other Decks in Programming
See All in Programming
AI コーディングエージェントの時代へ:JetBrains が描く開発の未来
masaruhr
2
220
Streamlitで実現できるようになったこと、実現してくれたこと
ayumu_yamaguchi
2
230
MCPを使ってイベントソーシングのAIコーディングを効率化する / Streamlining Event Sourcing AI Coding with MCP
tomohisa
0
190
リバースエンジニアリング新時代へ! GhidraとClaude DesktopをMCPで繋ぐ/findy202507
tkmru
4
1.3k
The Modern View Layer Rails Deserves: A Vision For 2025 And Beyond @ RailsConf 2025, Philadelphia, PA
marcoroth
2
820
それ CLI フレームワークがなくてもできるよ / Building CLI Tools Without Frameworks
orgachem
PRO
11
2.9k
Startups on Rails in Past, Present and Future–Irina Nazarova, RailsConf 2025
irinanazarova
0
310
JetBrainsのAI機能の紹介 #jjug
yusuke
0
110
Understanding Kotlin Multiplatform
l2hyunwoo
0
230
中級グラフィックス入門~効率的なメッシュレット描画~
projectasura
3
1.7k
The Evolution of Enterprise Java with Jakarta EE 11 and Beyond
ivargrimstad
0
530
slogパッケージの深掘り
integral0515
0
160
Featured
See All Featured
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.4k
Statistics for Hackers
jakevdp
799
220k
Bash Introduction
62gerente
613
210k
Done Done
chrislema
184
16k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
331
22k
Thoughts on Productivity
jonyablonski
69
4.8k
Mobile First: as difficult as doing things right
swwweet
223
9.7k
Designing Experiences People Love
moore
142
24k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
50k
[RailsConf 2023] Rails as a piece of cake
palkan
55
5.7k
A better future with KSS
kneath
238
17k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
7
760
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 のランタイムそのものを安 全にしてくれるわけではないので注意