なんでいま静的解析なの? PHPで学ぶ「静」と「動」

公開日:

広島市南区エールエールA館で開催された『PHPカンファレンス広島2025』でレギュラーセッション(20分)として発表しました。

Download PDF

スライドテキスト

Page 1

なんでいま静的解析なの?
PHPで学ぶ「静」と「動」

Why Static Analysis Now? Exploring “Static” and “Dynamic” in PHP

pixiv Inc.
USAMI Kenta

2025-10-11 #phpcon_hiroshima

PHPカンファレンス広島2025

Page 2

お前誰よ

  • うさみけんた (@tadsan) / Zonu.EXE / にゃんだーすわん
  • ピクシブ株式会社 Platform Div > WebTechnology Team PHPer
    • 2012年末から現職、APIとかCIとかいろいろなところを見つめてきました
  • Emacs PHP Modeを開発しています (2017年-)
  • プログラミング言語にちょっとこだわりのある素人 (spcamp2010)
  • 西日本とは縁もゆかりもなくて、広島に来たのは今日で三回目です!
  • assert(count($tadsan->phpcons) >= 45);

Page 3

今回のお題

Page 4

static dynamic

Page 5

プログラミングを
やっていると
ちょくちょく出てくる

Page 6

static

dynamic

Page 7

static

dynamic

Page 8

static

dynamic

Page 9

静とは 🧘

Page 10

引用:
英辞郎 on the WEB, 株式会社アルク, EDP

https://eowf.alc.co.jp/search?q=static
https://eowf.alc.co.jp/search?q=dynamic
(2025年10月11日 閲覧)

Page 11

引用:
英辞郎 on the WEB, 株式会社アルク, EDP

https://eowf.alc.co.jp/search?q=static
https://eowf.alc.co.jp/search?q=dynamic
(2025年10月11日 閲覧)

Page 12

引用:
英辞郎 on the WEB, 株式会社アルク, EDP

https://eowf.alc.co.jp/search?q=static
https://eowf.alc.co.jp/search?q=dynamic
(2025年10月11日 閲覧)

Page 13

引用:
英辞郎 on the WEB, 株式会社アルク, EDP

https://eowf.alc.co.jp/search?q=static
https://eowf.alc.co.jp/search?q=dynamic
(2025年10月11日 閲覧)

Page 14

動とは 🏃

Page 15

引用: dynamic - Wiktionary, the free dictionary (2025年8月12日 10:33版)

Page 16

活動・動いている

引用: dynamic - Wiktionary, the free dictionary (2025年8月12日 10:33版)

Page 17

活動・動いている

力強い・
エネルギッシュ

引用: dynamic - Wiktionary, the free dictionary (2025年8月12日 10:33版)

Page 18

活動・動いている

力強い・
エネルギッシュ

変化・適応できる

引用: dynamic - Wiktionary, the free dictionary (2025年8月12日 10:33版)

Page 19

活動・動いている

力強い・
エネルギッシュ

変化・適応できる

コンパイル時ではなく、
実行時に起こる

引用: dynamic - Wiktionary, the free dictionary (2025年8月12日 10:33版)

Page 20

Webにおける静と動
🌐

Page 21

Webページはいつ「変化」するか

  • 永遠に変化しない/新しいファイルをアップロードしたら変化する
  • 最初の表示は同じだが、人間が操作したら画面表示が変化する
  • ページをリロードするごとに新しい内容が表示される
  • 人間が操作するごとに新しい内容が表示される

Page 22

整理してみましょう

Page 23

Webページはどこで「変化」するか

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 24

Webページはどこで「変化」するか

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 25

Webページはどこで「変化」するか

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 26

Webページはどこで「変化」するか

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 27

Webページはどこで「変化」するか

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 28

Webアプリケーション分類

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 29

Webアプリケーション分類

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 30

フロントエンド

Webアプリケーション分類

アプリケーション

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 31

フロントエンド

Webアプリケーション分類

アプリケーション

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 32

フロントエンド

Webアプリケーション分類

アプリケーション

サーバーサイド

ブラウザ画面上で変化しない ブラウザ画面上で変化する

アプリケーション

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 33

静的ホスティング vs Webアプリ

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

↑ 静的ホスティングサーバー

内容は変わることがある テンプレートエンジン + hydration

(GitHub Pages, PHP/CGI非対応レンタルサーバ, HTTPサーバ単体)

Page 34

動的Webサーバ

(PHP)

ブラウザ画面上で変化しない ブラウザ画面上で変化する

↓ 動的サイト

サーバーが返す シングルページ
静的ページ

アプリケーションサーバ (PHP, Node.js, Go, Railsなど…)

内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 35

動的Webサーバ

(PHP)

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーサイド単体で
扱えるのはここ

↓ 動的サイト

サーバーが返す シングルページ
静的ページ

アプリケーションサーバ (PHP, Node.js, Go, Railsなど…)

内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 36

動的Webサーバ

(PHP)

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーサイド単体で ここの裏側にも
扱えるのはここ PHP APIがいる

↓ 動的サイト

サーバーが返す シングルページ
静的ページ

アプリケーションサーバ (PHP, Node.js, Go, Railsなど…)

内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 37

Webアプリ vs Next.js

(SSR)

ブラウザ画面上で変化しない ブラウザ画面上で変化する

Next.jsのようなフレームワークは

サーバーが返す シングルページ
静的ページ

これに特化している

内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

Vercel, AmplifyなどのPaaS
内容は変わることがある テンプレートエンジン + hydration

Page 38

Webアプリ vs Next.js

(SSG/SPA)

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す 静的ページ シングルページ 内容は常に同じ (SSG/静的サイト生成) アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

Next.jsは静的サイト開発にも使える

内容は変わることがある テンプレートエンジン + hydration

Page 39

Webアプリケーションの静と動

  • ここまでの説明はとても大雑把
  • 現実のWebサイトでは静的な要素と動的な要素が複雑に入り混じる
    • 静的なHTML/JSファイルからAPIにリクエストしてページ表示するとか
  • 静と動を適切に見極めて構成することで、開発効率やインフラコストの最適化
  • 従来はサーバーサイドアプリケーションが必要だったものも、
    近年では外部サービス(mBaaS/IDaaS)に依存することもできる

Page 40

静と動の境界を「ずらす」

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 41

静と動の境界を「ずらす」

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ

計算コストが重い

内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 42

静と動の境界を「ずらす」

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ

計算コストが重い

内容は常に同じ アプリケーション

キャッシュ
(CDN/キャッシュサーバ)

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 43

静と動の境界を「ずらす」

セッション依存(ログイン後) ページはキャッシュできない

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ

計算コストが重い

内容は常に同じ アプリケーション

キャッシュ
(CDN/キャッシュサーバ)

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 44

静と動の境界を「ずらす」

セッション依存(ログイン後) ページはキャッシュできない

適切にキャッシュ破棄できないと
古いコンテンツが残り続ける

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ

計算コストが重い

内容は常に同じ アプリケーション

キャッシュ
(CDN/キャッシュサーバ)

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 45

静と動の境界を「ずらす」

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 46

静と動の境界を「ずらす」

SEOが弱い
(クローリングが遅い)

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 47

静と動の境界を「ずらす」

SEOが弱い
(クローリングが遅い)

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

ダイナミックレンダリング

(Rendertron)

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 48

静と動の境界を「ずらす」

SEOが弱い
(クローリングが遅い)

いろんな意味で
運用だいぶつらい

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

ダイナミックレンダリング

(Rendertron)

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Page 49

静と動の境界を「ずらす」

SEOが弱い
(クローリングが遅い)

いろんな意味で
運用だいぶつらい

ブラウザ画面上で変化しない ブラウザ画面上で変化する

サーバーが返す シングルページ
静的ページ
内容は常に同じ アプリケーション

ダイナミックレンダリング

(Rendertron)

サーバーが返す サーバーサイド サーバーサイドレンダリング

内容は変わることがある テンプレートエンジン + hydration

Next.js移行

Page 50

静と動 🧘🏃

Page 51

動くものと
変わらぬものがある

Page 52

開発における静と動
🛠

Page 53

プログラムにも
静と動がある

Page 54

引用: PHP (プログラミング言語) - Wikipedia (2025年6月22日 14:23版)

Page 55

引用: PHP (プログラミング言語) - Wikipedia (2025年6月22日 14:23版)

Page 56

引用: PHP (プログラミング言語) - Wikipedia (2025年6月22日 14:23版)

Page 57

引用: C言語 - Wikipedia (2025年9月16日 22:41版)

Page 58

引用: Java - Wikipedia (2025年9月24日 16:18版)

Page 59

静的型付き

言語

(statically typed language)

  • 型検査 = プログラム(ソースコード)が型の制約を満たすか調べる
    • 例: 関数呼び出しに正しい型を渡せているか
  • 静的型付きの言語はプログラムの実行前に型検査合格を前提とする
    • 型がついたとき、実行時にその種のエラーが起こらない性質を
      「健全である」あるいは「型安全である」という
  • コンパイルの過程で型検査し、実行時に型情報を持たない言語も多い
  • 静的型付けと呼ぶのはおすすめしない (が、よく言われている)

Page 60

動的言語

(dynamic language)

  • プログラムの実行前に型検査合格を前提としない言語
  • 実行時に「値」と「型タグ」をセットで扱い、処理しながら逐次型検査を行なう
  • 実行時にソースコードを評価する(eval)など柔軟な機能を提供する
    • 原理上どんな文字列も実行できるので、無限の可能性を秘めている
  • 動的型付けと呼ぶのはおすすめしない (が、よく言われている)

Page 61

無限の彼方へ さあ行くぞ!

🚀🚀🚀

Page 62

無限とか言われても困る
😵💫

Page 63

品質管理 vs 俺たち

  • ソフトウェアを安定させるには、その挙動を予測可能な範囲に収めたい
  • 例:
    メソッドに期待する形式の引数を渡せば、エラーなく実行されてほしい
    • メソッドに同じ引数を渡せば、決まった結果になってほしい
    • わざわざ実装にジャンプしなくても、引数の形式がわかりやすくなってほしい
  • そこで、動的解析 = ユニットテスト = 動かして試してみる

Page 64

PHP vs 型付け

  • PHPは根本的に動的言語であり、ほとんどの特徴が当てはまる
  • ただしPHPには型宣言があり、型宣言通りの値が渡されなければエラー
  • 他言語でも型宣言は存在するが、実行時に保証されない口約束であることも
    • Python, TypeScript…
    • 一方でPHPでは動かしてみれば型宣言に反しているかがわかる

Page 65

PHP 5.x

Page 66

PHP 5.x PHP 7.x

Page 67

PHP 5.x PHP 7.x

安全性を落とさず
本質的な実装に集中できる

Page 68

Page 69

コーディングしながら
即座に間違いに気付きたい

Page 70

コーディングしながら
即座に間違いに気付きたい

Page 71

コーディングしながら
即座に間違いに気付きたい

Page 72

PHPStan

  • PHPStan - PHP Static Analysis Tool
    • フルネームで呼んでいる人は見たことがない
    • PHPで書かれたPHPの静的解析ツール
  • チェコ人のOndřej Mirtesが個人で開発している
    • 今年になってPHPStan s.r.o(有限会社)として法人化した

Page 73

PHPUnitと
同じようにCIで
使うもの…

Page 74

と考えてもいいが、
まずは小さく 使ってほしい

Page 75

インストラクション
PHPStanを使い倒せ

Page 76

PHPStanは 毎秒起動せよ

Page 77

……どうやって?

Page 78

テキストエディタに
組み込みましょう

Page 79

PhpStormで簡単に有効化

Page 80

VS Codeの場合

おそらくSanderRondeが
いちばんよくできてる

Page 81

VS Codeの場合

おそらくSanderRondeが
いちばんよくできてる

Page 82

Emacsは私が作っています

Page 83

常時ペアプロ相手に
なってくれてる
ようなもの

Page 84

Page 85

Page 86

\PHPStan\dumpType()

Page 87

PHPStanの
基本機能を使える
ようになろう

Page 88

Page 89

Page 90

無限の可能性を
認識可能な範囲内に
縮めるのが型

Page 91

実行しなくても
わかること
= 静的に確認したい

Page 92

実行して
確かめたいこと

= PHPUnit

Page 93

静と動

Page 94

静的解析とテスト

Page 95

どちらかではなく
両輪

Page 96

PHPStanが
変だなと思ったら

Page 97

phpusers-ja Slack

Page 98

続きはWebで