Page 1
実践PHPStan
Practical PHPStan
pixiv Inc.
USAMI Kenta
PHP Conference Okinawa 2022
2022-08-27
公開日:
by USAMI Kenta @tadsan
に沖縄県那覇市のZORKS沖縄 および YouTube Liveで開催された『PHPカンファレンス沖縄2022』でレギュラートーク(30分)として発表しました。
実践PHPStan
Practical PHPStan
pixiv Inc.
USAMI Kenta
PHP Conference Okinawa 2022
2022-08-27
お前誰よ
tadsanのあれこれが読める場所
https://www.phper.ninja/
https://scrapbox.io/php/
今回のお題
プロポーザル
先日、型についての話もしました
PHPカンファレンスでも話しました
今回のゴール
PHPStanで型を付けて
既存コードの型を検査
今回やらないこと
PHPStanの詳細な設定
CI環境の組み方
ジェネリクス/条件型
ジェネリクスについて
条件付き戻り値型
このスライドは
本日中に公開されます
この発表では知っておくべき機能 を雑に取り上げるので本番運用/ 提案の前にドキュメントを自身で
しっかり読み込みましょう。
それでもわからないことがあれば TwitterかSlackのphpusers-ja
#type-safeで尋ねてください
PHPStan
使ってますか?
PHPStanとは何か
リ ン タ ー
なに? 使ってない?
あなたとPHPStan いますぐダウンロー
ド
どうやって?
Ond ej said...
ř
PHP 7.2以上ならプロジェクトに追加しよう
composer require--dev
phpstan/phpstan
プロジェクトに追加できないなら
composer globalrequire
phpstan/phpstan
require --dev以外の方法を検討
PHPStanを入れてどうするの
PhpStormがあるのに必要…?
解析結果はリアルタイム表示しよう
(場合によって要設定)
+
(Marketplaceには古いのもあるので注意)
(私が作っています)
(汎用言語サーバー)
外した方がいいPhpStorm設定
外した方がいいPhpStorm設定
arrayと
array<mixed>と
mixed[] を混同しない
外した方がいいPhpStorm設定
@param とか @returnを
執拗に全部埋めてくる
arrayと
array<mixed>と
mixed[] を混同しない
ここ最近のPHPStan
⛱
PHPStanは何ではないか
(Ondřej Mirtes)
PHPの型の基礎
型の基本的な考え方
ユニオン型
A|B
AまたはB
(複雑な式は書けない)
交(cid:20281)型
A&B
AおよびB
(複雑な式は書けない)
型
DNF
int|A|(B&C)|null
intまたはAまたは「BおよびC」またはnull
(一定の制約下で複雑な型も書ける)
null許容型
?
A
Aまたはnull
デフォルトで許容しない
謎のPHP用語
mixed
任意の(すべての)型を表す型
(ほかの言語でのany)
型をどこに書くか
型宣言
(type declaration)
型宣言
(type declaration)
型宣言
(type declaration)
型宣言
(type declaration)
型宣言
(type declaration)
型注釈
(type annotation)
型注釈
(type annotation)
型注釈
(type annotation)
型宣言 vs PHPDoc(型注釈)
無駄なPHPDocは書かない
外した方がいいPhpStorm設定
(再掲)
外した方がいいPhpStorm設定
(再掲)
arrayと
array<mixed>と
mixed[] を混同しない
外した方がいいPhpStorm設定
(再掲)
@param とか @returnを
執拗に全部埋めてくる
arrayと
array<mixed>と
mixed[] を混同しない
型宣言があれば
PHPDocなくても
足りるんじゃないの?
PHPStanには
もっと強力な型がある
PHPStanを 使ってみよう
オンライン
サンドボックス
いますぐダウンロー
ド
いますぐダウンロー
ド
しなくてもいい
https://phpstan.org/try
こういう関数を
考えてみましょう
型宣言で型のついた完璧な関数
型宣言で型のついた完璧な関数
本を検索する関数
型宣言で型のついた完璧な関数
本を検索する関数
検索ワード
型宣言で型のついた完璧な関数
本を検索する関数
検索ワード
何これ
型宣言で型のついた完璧な関数
本を検索する関数
検索ワード
何これ
何これ
PHPStan第一の関門(レベル6)
PHPStan第一の関門(レベル6)
$options
配列の中身わからん
PHPStan第一の関門(レベル6)
$options
配列の中身わからん
returnされる
配列の中身わからん
再度完璧に型を付けた関数
再度完璧に型を付けた関数
配列の中身には あらゆる可能性
型を表示してみる
取り出してきた値の配列
取り出してきた値の配列
配列の中身わからん
型がついていないとはどういうことか
このプログラムが正しいか判断できない
必要のないところにmixedは書かない
コードに型を付ける
型宣言があれば
足りるんじゃないの?
型宣言だけでは
表現力が不足している
array
“配列”の曖昧さ
別途arrayの話もしました
配列はひとつ!じゃない!!
配列はひとつ!じゃない!!
list<int>
配列はひとつ!じゃない!!
list<int>
array<int,string>
配列はひとつ!じゃない!!
list<int>
array<int,string>
array{id:int, name:string}
[
['id' => 123, 'name' => '野比のび太'],
['id' => 234, 'name' => '源静香'],
]
配列はひとつ!じゃない!!
list<int>
array<int,string>
array{id:int, name:string}
[
['id' => 123, 'name' => '野比のび太'],
['id' => 234, 'name' => '源静香'],
]
list<array{id:int, name:string}>
array-shapes
(またはobject-like arrays)
arrayに詳細に型を付ける
arrayに詳細に型を付ける
fullかpartialのみ
取り出してきた値の配列
取り出してきた値の配列
取り出してきた値の配列
fullかpartialなのに
perfect
取り出してきた値の配列
fullかpartialなのに
perfect
ほんとはtitleなのに
nameでアクセス
PHPStanの
強力な型
型名について
(先
\
が一般的だが、bookのように小文字も定義可
頭と単語区切りを大文字にする)
\never
整数範囲型
リテラル型・定数型
key-of型・value-of型
PHPDocに書ける配列の型について
array-shapes
(Object-like arrays)
array<Type>
list<Type>
non-empty-*型
先程のコードを拡張する
先程のコードを拡張する
検索モードのリスト
先程のコードを拡張する
検索モードのリスト
value-of<定数>
先程のコードを拡張する
検索モードのリスト
value-of<定数>
価格は正の整数
先程のコードを拡張する
検索モードのリスト
value-of<定数>
空文字列を
検索禁止する
価格は正の整数
呼出し側のコード
呼出し側のコード
(警告)
空文字列を検索
呼出し側のコード
(警告)
空文字列を検索
(警告)
price == 0 はありえない
ばっちり型が つきましたね
基本的な型の付け方
array{} とか
覚えなくてよくない?
そういう意見もある
DTO
(Data Transfer Object)
PHP 8.1時代のコード
PHP 8.1時代のコード
検索モード
PHP 8.1時代のコード
検索モード
オプションは配列
ではなくクラス
PHP 8.1時代のコード
PHP 8.1時代のコード
著者
PHP 8.1時代のコード
著者
書籍
PHP 8.1時代のコード
著者
書籍
コンストラクタ プロモーション
PHP 8.1時代のコード
PHP 8.1時代のコード
オプション型宣言
PHP 8.1時代のコード
オプション型宣言
戻り値PHPDoc
クラス vs array
かくしてPHPに
完璧な型がつきました
めでたしめでたし
😇
これで済むなら
PHPは型なしとか
呼ばれてない
型なしは
どこから来るの?
動的型 vs 型なし
型なしの値
😇
型を絞り込もう
PHPStan dumpType()
\
dumpType()関数で型を表示
dumpType()関数で型を表示
関数に渡す
dumpType()関数で型を表示
関数に渡す
dumpType()関数で型を表示
関数に渡す
もちろんPhpStorm上
で表示できる
check & throw
check & throw
falseだったら
関数を抜けることで
check & throw
falseが混じる
falseだったら
可能性を排除
関数を抜けることで
assert
(表明)
assert
(表明)
falseではないと表明
assert
(表明)
falseが混じる 可能性を排除
falseではないと表明
PHPStanは分岐ごとに型を保持
PHPStanは分岐ごとに型を保持
分岐ごとに範囲が分かれ
合流すると戻る
DIコンテナ
任意の値を格納できるコンテナ
超適当に実装して
値をコンテナに詰め込む
値をコンテナから取り出す
値をコンテナから取り出す
値をコンテナから取り出す
値をコンテナから取り出す
変数すべてmixed
値をコンテナから取り出す
変数すべてmixed
型が不定のメソッド
呼び出し
assertによるインライン型付け
@varによるインライン型付け
if/assert vs @var
if/assert vs @var の使い分け案
標準関数 vs 型
簡潔だが型安全ではないコード
几帳面にチェックする実装
実行時/型安全なラッパー関数
まとめ
PHPStanは オンラインで
型チェックできる
https://phpstan.org/try
PHPStanは 完璧じゃない
期待した型がつかない
と思ったら最小の
コードをオンラインで
チェックしましょう
バグの場合もあるし 実装してPRを送る
チャンスかもしれない
今回スルーした型
ジェネリクス
条件付き戻り値型
そもそも自明な型は付けたくない
こういう型を付けられると嬉しい
現在のPHPStanの
仕様上このような型は
つけられない
そのうち
(誰かが実装完了すれば) 改善する見込みはある
PHPStanの実装は
超簡単だとは言えないが 仕事でPHPやってたら 手を出せないほど難解と
いうほどではない
みなさんもチャレンジ
してみましょう
PHPStanで
楽しい型付けライフを