Slide 1

Slide 1 text

@maikeru (mikumo) PHP 7 系と PHP 8 系の違いを ラッパー関数を作って確認する

Slide 2

Slide 2 text

@maikeru (mikumo) 自己紹介✍ 三雲 勇二 / mikumo プライム・ストラテジー株式会社 所属 ・KUSANAGI / WEXAL (WordPress などフレームワーク高速化) ・ハイパーオートメーション (自動化やAIなど) ・PRIME STUDY (PHPの模擬試験あります) PHP技術者認定機構 エバンジェリスト ・PHP試験のコラムを毎月書いてます ・来年春公開予定の新試験「PHP8初級」の監修

Slide 3

Slide 3 text

@maikeru (mikumo) PHP 7 系のサポートが切れ 1ヶ月たちましたね

Slide 4

Slide 4 text

@maikeru (mikumo) PHP バージョン別シェア § W3Techs: https://w3techs.com/technologies/details/pl-php

Slide 5

Slide 5 text

@maikeru (mikumo) ですよね😶

Slide 6

Slide 6 text

@maikeru (mikumo) ということで、 PHP 8 系への移行は まだまだ残っています

Slide 7

Slide 7 text

@maikeru (mikumo) 暫定対応でよく使う方法として ラッパー関数を用意する手法 があります。

Slide 8

Slide 8 text

@maikeru (mikumo) implode 関数の ラッパー関数を作って 違いを見てみましょう。

Slide 9

Slide 9 text

@maikeru (mikumo) 今回の環境です。 動作環境: PHP 8.2 エミュレート: PHP 7.4

Slide 10

Slide 10 text

@maikeru (mikumo) implode 関数 § PHP Documentation: https://www.php.net/manual/ja/function.implode.php

Slide 11

Slide 11 text

@maikeru (mikumo) implode 関数 § PHP Documentation: https://www.php.net/manual/ja/migration80.incompatible.php 1. implode(string $separator, array $array): string 2. implode(array $array): string 3. implode(array $array, string $separator): string

Slide 12

Slide 12 text

@maikeru (mikumo) implode 関数の PHP 8.0 変更点 § PHP Documentation: https://www.php.net/manual/ja/migration80.incompatible.php ($pieces, $glue) のような形で、 implode() 関数を逆の引数の順番で呼ぶ ことはサポートされなくなりました。

Slide 13

Slide 13 text

@maikeru (mikumo) implode 関数 § PHP Documentation: https://www.php.net/manual/ja/migration80.incompatible.php 1. implode(string $separator, array $array): string 2. implode(array $array): string 3. implode(array $array, string $separator): string 3番目の書き方は PHP 8.0 で廃止

Slide 14

Slide 14 text

@maikeru (mikumo) つまり、 引数の順番が間違っていたら 入れ替えれば良いのね😃

Slide 15

Slide 15 text

@maikeru (mikumo) implode ラッパー関数 function php74_implode($separator, $array) { // implode($array, $separator) 対応 if (is_string($array) && is_array($separator)) { return implode($array, $separator); } return implode($separator, $array); }

Slide 16

Slide 16 text

@maikeru (mikumo) できたー😃

Slide 17

Slide 17 text

@maikeru (mikumo) いいえ 残念ながらコレではダメです🤔

Slide 18

Slide 18 text

@maikeru (mikumo) 問題 1 : 引数の型 § PHP Documentation: https://www.php.net/manual/ja/migration80.incompatible.php PHP 7 系までは引数の型は特に指定されていません。 implode($separator, $array) PHP 8 系は引数の型がチェックされるように書いています。 (が、実はそうでもないです。) implode(string $separator, array $array): string

Slide 19

Slide 19 text

@maikeru (mikumo) 問題 2 : 戻り値の型 § PHP Documentation: https://www.php.net/manual/ja/migration80.incompatible.php PHP 7 系までは戻り値の型が指定されていません。 implode($separator, $array) PHP 8 系は戻り値の型が指定されます。 (が、実はそうでもないです。) implode(string $separator, array $array): string

Slide 20

Slide 20 text

@maikeru (mikumo) これを踏まえると

Slide 21

Slide 21 text

@maikeru (mikumo) implode ラッパー関数 function php74_implode(mixed $separator, mixed $array): string { // implode($array, $separator) 対応 if (is_string($array) && is_array($separator)) { return implode($array, $separator); } return implode($separator, $array); }

Slide 22

Slide 22 text

@maikeru (mikumo) まだ、 コードにも改善点があります。

Slide 23

Slide 23 text

@maikeru (mikumo) 問題 3 : return する順番 まず正常系をさっさと return させます。 • implode(string $separator, array $array): string • implode(array $array): string 異常系でエミュレートすべきコードは下げます。 • implode(array $array, string $separator): string • 引数の型が絞られたことによる対応

Slide 24

Slide 24 text

@maikeru (mikumo) 問題 4 : グローバル関数を明示 グローバル関数であることをはっきり明示するよう、名前空間を利用する。 ✗ implode($separator, $array); ○ \implode($separator, $array);

Slide 25

Slide 25 text

@maikeru (mikumo) implode ラッパー関数 function php74_implode(mixed $separator, mixed $array): string { // \implode(string $separator, array $array): string if (is_string($separator) && is_array($array)) { return \implode($separator, $array); } // \implode(array $array): string if (is_array($separator) && $array === null) { return \implode($separator); } (ここから下に PHP 7.4 をエミュレートするコードを書く)

Slide 26

Slide 26 text

@maikeru (mikumo) 引数はどんな型でも受け付ける …けど、本当に正しいの?

Slide 27

Slide 27 text

@maikeru (mikumo) 実際に PHP 7.4 の implode 関数の引数に いろんな型を入れてみました。

Slide 28

Slide 28 text

@maikeru (mikumo) PHP 7.4 implode 関数の動作確認 // implode(array $array): string $array = null; var_dump( implode($array) ); • PHP 7.4: null が戻ってきた。 • PHP 8.2: エラー

Slide 29

Slide 29 text

@maikeru (mikumo) 問題 5 : エラーレベルの変更 PHP 8 系ではエラーレベルがより上位のエラーレベルに変更されている物が 多い。 ✗ implode($separator, $array); ○ \implode($separator, $array);

Slide 30

Slide 30 text

@maikeru (mikumo) PHP 7.4 implode 関数の動作確認 // implode(array $array): string $array = 'example'; var_dump( implode($array) ); • PHP 7.4: null が戻ってきた。 • PHP 8.2: エラー

Slide 31

Slide 31 text

@maikeru (mikumo) PHP 7.4 implode 関数の動作確認 // implode(array $array): string $separator = null; $array = null; var_dump( implode($separator, $array) ); • PHP 7.4: null が戻ってきた。 • PHP 8.2: エラー

Slide 32

Slide 32 text

@maikeru (mikumo) PHP 7.4 implode 関数の動作確認 // implode(array $array): string $separator = true; $array = [1, 2, 3]; var_dump( implode($separator, $array) ); • PHP 7.4: 123 • PHP 8.2: 123 ($separator は boolean なのにエラーじゃない)

Slide 33

Slide 33 text

@maikeru (mikumo) いわゆる ブラックボックステスト ですね。

Slide 34

Slide 34 text

@maikeru (mikumo) implode ラッパー関数 (ここより上が正常系) if ($separator === null && is_array($array)) { return \implode($array); } if (is_array($separator)) { return \implode((string)$array, $separator); }

Slide 35

Slide 35 text

@maikeru (mikumo) implode ラッパー関数 if ($separator === null && is_array($array)) { return \implode($array); } if ($array === null) { return null; } return null; }

Slide 36

Slide 36 text

@maikeru (mikumo) ちなみに確認用で PHPUnit テストコード 1,000 ケース以上書きました。

Slide 37

Slide 37 text

@maikeru (mikumo) 今回のまとめ • PHP 8 系で始まった型の厳密化の影響は、こんなところにもでる • 公式ドキュメントだけで考えず、必ず実行して試してみる • PHP は型を意識したプログラミングが重要になっていく

Slide 38

Slide 38 text

@maikeru (mikumo) ありがとうございました