PHPでstartsWidthやendsWidth

アキラ
PHPで、javascriptみたいなstartWidthとかendWidthないから不便だよね。
ワタル
あるよ。
アキラ
えっ。あんの?
ワタル
うん。PHP8からできた。
str_starts_with — 文字列が指定された部分文字列で始まるかを調べる
str_ends_with — 文字列が、指定された文字列で終わるかを調べる。
アキラ
この記事終わりだね。
ワタル
いやいやPHP8使えない環境あるでしょ。
アキラ
そんなレガシーな環境しか使えない会社転職でしょ。
将来のキャリアに不安なら【IT求人ナビ転職】
ワタル
そんなぁ。話進めるよ。
アキラ
登録してみるといい会社結構あるのに...

🐎

<?php
    
function startsWith($haystack, $needle) {
    return @strncmp($haystack, $needle, strlen($needle)) === 0;
}

function endsWith($haystack, $needle) {]
    return !@strlen($needle) ?: (substr_compare($haystack, $needle, -strlen($needle)) === 0);
}

echo(var_export(startsWith('aabbcc', 'aab')) . \"n");  // true
echo(var_export(startsWith('aabbcc', 'bcc')) . "\n");  // false
echo(var_export(startsWith('aabbcc', '')) . "\n");  // true
echo(var_export(endsWith('aabbcc', 'aab')) . "\n");  //false
echo(var_export(endsWith('aabbcc', 'bcc')) . "\n");  // true
echo(var_export(endsWith('aabbcc', '')) . "\n");  // true
ワタル
解説するよ。
アキラ
よろしく。
ワタル
ポイントは2つ。
まずは、startsWithで、strncmp使っているところ
アキラ
あまり聞かないよね
ワタル
うん。 ネットとかでstartsWith作るときにstrposが0かどうかで判定してるコード落ちてたりするけど、strposだと$haystackの先頭になくても、場所を返す関数だから最後まで$needleを探しに行くから効率的じゃない。その点strncmp
strncmp — 最初の n 文字についてバイナリセーフな文字列比較を行う
ワタル
なので、最初しか見ないんだ。
アキラ
なるほど。
ワタル
2つ目のポイントは、endsWithで最初に!@strlen($needle) ?: なんてややこしいことやってるけど、これは、PHP8純正のstr_ends_withに挙動を合わせてるんだ。
アキラ
というと?

🐢

<?php

echo(var_export(str_ends_with('aabbcc', '')) . "\n");  // true
echo(var_export(str_ends_with('aabbcc', null)) . "\n");  // true
echo(var_export(str_ends_with('aabbcc', false)) . "\n");  // true
echo(var_export(str_ends_with('aabbcc', true)) . "\n");  // false
echo(var_export(str_ends_with('aabbcc', 0)) . "\n");  // false
ワタル
空文字とかnullを入れたときの戻りのことね。ここらへんがずれてるとめでたくPHP8導入してstr_ends_withに置き換えたときに変なバグになるからね。
アキラ
そういうバグ見つけにくいんだよねー。