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
470
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
どうして手を動かすよりもチーム内のコードレビューを優先するべきなのか
okashoi
2
40
パスワードのハッシュ、ソルトってなに? - What is hash and salt for password?
okashoi
3
110
設計の考え方 - インターフェースと腐敗防止層編 #phpconfuk / Interface and Anti Corruption Layer
okashoi
10
2.9k
"config" ってなんだ? / What is "config"?
okashoi
0
700
ファイル先頭の use の意味、説明できますか? 〜PHP の namespace と autoloading の関係を正しく理解しよう〜 / namespace and autoloading in php
okashoi
3
1.1k
MySQL のインデックスの種類をおさらいしよう! / overviewing indexes in MySQL
okashoi
0
690
【PHPカンファレンス沖縄 2023】素朴で考慮漏れのある PHP コードをテストコードとともに補強していく(ライブコーディング補足資料) / #phpcon_okinawa 2023 livecoding supplementary material
okashoi
3
1.8k
その説明、コードコメントに書く?コミットメッセージに書く? プルリクエストに書く? - #phpconfuk 2023
okashoi
15
5k
いろいろなフレームワークの仕組みを index.php から読み解こう / index.php of each framework
okashoi
2
2.7k
Other Decks in Programming
See All in Programming
Cloudflare MCP ServerでClaude Desktop からWeb APIを構築
kutakutat
1
550
Go の GC の不得意な部分を克服したい
taiyow
3
790
PHPUnitしか使ってこなかった 一般PHPerがPestに乗り換えた実録
mashirou1234
0
190
42 best practices for Symfony, a decade later
tucksaun
1
180
Security_for_introducing_eBPF
kentatada
0
110
暇に任せてProxmoxコンソール 作ってみました
karugamo
2
720
開発者とQAの越境で自動テストが増える開発プロセスを実現する
92thunder
1
190
採用事例の少ないSvelteを選んだ理由と それを正解にするためにやっていること
oekazuma
2
1k
Semantic Kernelのネイティブプラグインで知識拡張をしてみる
tomokusaba
0
180
快速入門可觀測性
blueswen
0
370
From Translations to Multi Dimension Entities
alexanderschranz
2
130
創造的活動から切り拓く新たなキャリア 好きから始めてみる夜勤オペレーターからSREへの転身
yjszk
1
130
Featured
See All Featured
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
48
2.2k
For a Future-Friendly Web
brad_frost
175
9.4k
Why Our Code Smells
bkeepers
PRO
335
57k
Optimizing for Happiness
mojombo
376
70k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Java REST API Framework Comparison - PWX 2021
mraible
28
8.3k
GitHub's CSS Performance
jonrohan
1030
460k
Designing for Performance
lara
604
68k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
95
17k
How To Stay Up To Date on Web Technology
chriscoyier
789
250k
Why You Should Never Use an ORM
jnunemaker
PRO
54
9.1k
How to Think Like a Performance Engineer
csswizardry
22
1.2k
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 のランタイムそのものを安 全にしてくれるわけではないので注意