Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHP における静的解析(あるいはそもそも静的解析とは) / #phpcondo_yasai ...

PHP における静的解析(あるいはそもそも静的解析とは) / #phpcondo_yasai static analysis for PHP

2024/01/11 開催「PHPカンファレンス北海道2024 全然野菜」(https://connpass.com/event/298365/ )の発表資料です。

Shohei Okada

January 11, 2024
Tweet

More Decks by Shohei Okada

Other Decks in Programming

Transcript

  1. PHP の静的解析ツール例 · php -l コマンド · PHPMD · PHP_CodeSniffer(phpcs)

    · PHPStan ←本日取り上げるのはこちら · Psalm · Phan · (PhpStrom)
  2. A. 変数の typo <?php $environment = $_ENV['APP_ENV']; if ($enviroment ===

    'production') { // ... } https://phpstan.org/try
  3. <?php /** @var string $heystack */ if (strpos($heystack, 'a') ===

    fasle) { // ... } https://phpstan.org/try Q. 何がおかしい?
  4. <?php /** @var string $heystack */ if (strpos($heystack, 'a') ===

    fasle) { // ... } https://phpstan.org/try A. Boolean リテラルの typo
  5. <?php /** @var string $dsn */ $pdo = new PDO($dsn);

    $statement = $pdo->prepare('SELECT * FROM users WHERE id = ?;'); $statement->executeStatement([1]); https://phpstan.org/try Q. 何がおかしい?
  6. <?php /** @var string $dsn */ $pdo = new PDO($dsn);

    $statement = $pdo->prepare('SELECT * FROM users WHERE id = ?;'); $statement->executeStatement([1]); https://phpstan.org/try A. 存在しないメソッド
  7. <?php function getMonth(DateTimeImmutable $dt): int { return $dt->format('n'); } $now

    = new DateTime(); echo getMonth($now); https://phpstan.org/try Q. 何がおかしい?
  8. <?php function getMonth(DateTimeImmutable $dt): int { return $dt->format('n'); } $now

    = new DateTime(); echo getMonth($now); https://phpstan.org/try A. 戻り値の型の不整合
  9. <?php function getMonth(DateTimeImmutable $dt): int { return $dt->format('n'); } $now

    = new DateTime(); echo getMonth($now); https://phpstan.org/try A. 引数の型の不整合
  10. <?php /** @var string $heystack */ $index = strpos($heystack, 'a');

    echo substr($heystack, $index); https://phpstan.org/try Q. 何がおかしい?
  11. https://phpstan.org/try <?php /** @var string $heystack */ $index = strpos($heystack,

    'a'); echo substr($heystack, $index); A. 型の不整合(false チェック漏れ)
  12. 余談)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; }
  13. 余談)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; }