PHP8.0で、部分文字列を扱う関数が3つ追加されました。
str_contains(), str_starts_with(), str_ends_with() 。
この3つの関数じゃなくても比較的かんたんに同じ処理が書けるんですが、あえて新関数が用意されました。
str_contains, 文字列内の部分文字列の存在チェックを行う。
さっそく、新関数の内容を見ていきましょう。まずは str_contains() です。
この関数は、文字列の中に、ある部分文字列があるか? ないか? のチェックを行います。
$str = 'xxxabcyyy';
$search = 'abc';
if (true === str_contains($str, $search)) {
echo 'string [' . $search . '] matches' . PHP_EOL;
}
$search = 'abd';
if (true !== str_contains($str, $search)) {
echo 'string [' . $search . '] unmatches' . PHP_EOL;
}
string [abc] matches
string [abd] unmatches
『あれ? この関数じゃなくてもできたんじゃなかったっけ?』と思った人はおそらく、strpos() を想像したと思います。
この処理は、if文の判定を true じゃなく false で見れば、関数名をstrpos() するだけでまったく同じ処理ができます。
それぐらい似ている。
ちゃんと日本語(全角文字)などのマルチバイト文字にも対応していますよ。
str_starts_with, 文字列が部分文字列から始まっているかをチェックする。
str_starts_with() は、文字列が指定した部分文字列で始まっているかをチェックします。
$str = 'abcdefg';
// 開始文字列が一致
$start = 'abc';
$result = str_starts_with($str, $start);
if ($result) {
echo 'string start with ' . "'" . $start . "'" . PHP_EOL;
}
$pattern = '/' . $start . '.*/';
$result = preg_match($pattern, $str);
if ($result) {
echo 'string start with ' . "'" . $start . "'" . PHP_EOL;
}
// 開始文字列が不一致
$start = 'ac';
$result = str_starts_with($str, $start);
if (!$result) {
echo 'string not start with ' . "'" . $start . "'" . PHP_EOL;
}
$pattern = '/' . $start . '.*/';
$result = preg_match($pattern, $str);
if (!$result) {
echo 'string not start with ' . "'" . $start . "'" . PHP_EOL;
}
string start with 'abc'
string start with 'abc'
string not start with 'ac'
string not start with 'ac'
これは、preg_match() を使えば同じ処理が同じくらいのコードボリュームで書けます。
ただし、新関数のほうが正規表現の知識がいらないのでかんたん。
『〇〇で開始した文字列を検索する』処理は使用頻度が高いので、よりかんたんなものを用意したのでしょう。
これもマルチバイト文字に対応しているので、日本語(全角文字)でも使えます。
str_ends_with, 文字列が部分文字列で終わっているかをチェックする。
str_ends_with() は『始まりがあれば終りがある』みたいなもので、str_starts_with() の文字列の終わりを見るバージョンです。
関数名も 'start' が 'end' に変わっただけでほぼ同じ。(後ろに 's' が付くので注意。)
もちろん日本語に対応しています。
str_starts_with() と str_ends_with() はセットで覚えましょう。
$str = 'xyzabc';
// 文字列の末尾が一致
$end = 'abc';
$result = str_ends_with($str, $end);
if ($result) {
echo 'string end with ' . "'" . $end . "'" . PHP_EOL;
}
$pattern = '/.*' . $end . '/';
$result = preg_match($pattern, $str);
if ($result) {
echo 'string end with ' . "'" . $end . "'" . PHP_EOL;
}
// 文字列の末尾が不一致
$end = 'ac';
$result = str_ends_with($str, $end);
if (!$result) {
echo 'string not end with ' . "'" . $end . "'" . PHP_EOL;
}
$pattern = '/.*' . $end . '/';
$result = preg_match($pattern, $str);
if (!$result) {
echo 'string not end with ' . "'" . $end . "'" . PHP_EOL;
}
string end with 'abc'
string end with 'abc'
string not end with 'ac'
string not end with 'ac'
既存関数でもできるのになんであえて関数を作った?
PHP8.0 で追加された部分文字列の新関数3つは、どれも既存の関数でしかも比較的シンプルなコーディングで処理が書けます。
それでもあえて新関数が作られました。
関数名に忠実になるための追加
理由の一つは関数の意味に忠実になったこと。
strpos() はもともと、関数内にある部分文字列のポジションを返すものです。
戻り値は部分文字列が無いか処理に失敗すると false、あればその位置の数値を返す。
今までは、部分文字列の存在チェック用の関数が無かったので代用していたに過ぎません。
プログラム言語では関数名は大事です。そこに処理の答えが一言であるから。
プログラミングでは何がしたいか?(どの関数を使うか?)というとき、まっ先に関数名を見ます。
'strpos' を見て部分文字列の存在チェックを想像できる人はまずいません。
代用をほっとくと関数名の意味がなくなってしまうんですね?
こういうパターンで新関数が作られることはけっこう多いです。
代用が一般化しすぎて慣れすぎてると、なかなか使わないことも多いけど。
使用頻度が高い処理を関数として独立させる
新関数を作ったもう一つの理由は処理の使用頻度が高そうだから。こういうパターンもよくあります。
この理由で作られた関数は処理の機能が特化されることが多く、汎用性はありません。
preg_match() は正規表現を使うので、文字列のパターンを見るものではかなり高機能なもの。
かんたんなことをしたいだけで、そこまで高機能なものはいらないことはよくあります。
こういう新関数も昔の使い方に慣れすぎてると、なかなか使わないものになりやすいけど。