便利だけど使う前に挙動をしっかり理解しておきたいので。
予習メモです。
環境構築
PHP8の環境を用意します。
開発環境を汚したくない場合はDockerがおすすめです。
簡単なスクリプトならDockerfileを作成する必要もありません。
rmオプションを使用することにより、スクリプト実行後にコンテナが削除されます。
$ mkdir php8_test
$ cd php8_test
$ vi mytest.php
$ docker run -it --rm --name my-running-script -v "$PWD":/usr/src/php8_test -w /usr/src/php8_test php:8.0-cli php mytest.php
公式ドキュメントにも紹介されています。
数値と文字列の比較
数値と文字列の比較について、文字列が数値形式か否かで変換の対象が変わります。
公式サイトより
数値形式の文字列と比較する場合は、PHP 8 は数値として比較を行います。それ以外の場合は、数値を文字列に変換し、文字列として比較を行います。
PHP7以前
'foobar'を数値に変換して比較します。
(int)'foobar'は0なので、結果がtrueになってしまいます。
公式サイトより
文字列が 数値形式の文字列 の場合は、対応する整数値に解決されます。 そうでない場合は、ゼロ (0) に変換されます。
mytest.php
var_dump(0 == 'foobar');
//> bool(true)
var_dump(in_array(0, ['foobar']));
//> bool(true)
PHP8以降
'foobar'は数値形式の文字列ではないので、0を文字列に変換して比較します。
(string)0は'0'なので、結果はfalseになります。
mytest.php
var_dump(0 == 'foobar');
//> bool(false)
var_dump(in_array(0, ['foobar']));
//> bool(false)
match式
PHP8から追加されたmatch式を紹介します。
「厳密な比較ができるswitch文」として利用できそうです。
公式サイトより
match 式は、値の一致をチェックした結果に基づいて評価結果を分岐します。 switch 文と似ていますが、 match 式は複数の候補と比較される制約式を持ちます。 switch 文とは異なり、 三項演算子のように値を評価します。 switch 文とは異なり、 弱い比較(==)ではなく、 型と値の一致チェック(===) に基づいて行われます。
$return_value = match (制約式) {
単一の条件式 => 返却式,
条件式1, 条件式2 => 返却式,
};
PHP7以前
ご存知のとおり、switch文では厳密な比較(===)が行われません。
mytest.php
$param = 1;
# switch文
switch ($param) {
case '1':
str_func();
break;
case 1:
int_func();
break;
default:
default_func();
}
//> Param is string!
function str_func()
{
echo "Param is string!\n";
}
function int_func()
{
echo "Param is integer!\n";
}
function default_func()
{
echo "Default!\n";
}
そのため、条件分岐で厳密な比較を行う場合はif文や三項演算子を利用する必要がありました。
mytest.php
# if文
if ($param === '1') {
str_func();
} elseif ($param === 1) {
int_func();
} else {
default_func();
}
//> Param is integer!
# 三項演算子
$param === '1' ? str_func() : ($param === 1 ? int_func() : default_func());
//> Param is integer!
match式の使いどころ
「本当はswich文を使いたいけれど厳密な比較が出来ないから使えない・・・ぐぬぬ・・・」のような分岐が多い処理で役に立ちます。
下記コードのように$paramの種類ごとに処理が存在する場合は活躍できそうです。
また、記述できるのは一行の式だけですがbreak;が必要ないためコードがスッキリします。
mytest.php
match ($param) {
'1' => str_func(),
1, => int_func(),
default => default_func(),
};
//> Param is integer!
逆に分岐が少ない場合はさほどメリットが無いかもしれません。
match式で厳密な比較を行わない方法
興味深い使い方もありました。
公式サイトより
制約式に true を指定することで、 厳密な一致チェックを行わずに match 式を使うことができます。
下記コードは制約式にtrueを指定しているため、条件式のin_array($param, $str_arr)の結果を元に条件分岐が行われます。
ですがin_arrayの第3引数にtrueが指定されていないので厳密な比較が実行されず、match式の結果にもそれが反映されてしまいます。
mytest.php
$param = 1;
$str_arr = ['1', '2'];
$int_arr = [1, 2];
// 制約式にtrueを指定
match (true) {
in_array($param, $str_arr) => str_func(),
in_array($param, $int_arr) => int_func(),
default => default_func(),
};
//> Param is string!
この場合は条件式で厳密な比較を行う必要があります。
mytest.php
match (true) {
in_array($param, $str_arr, true) => str_func(),
in_array($param, $int_arr, true) => int_func(),
default => default_func(),
};
//> Param is integer!
新しい機能は使いたくなるのが人の常ですが、使いどころは見極めていきたいです。
↧