この記事はPHP 8.1.11を使用しています。
strrevがマルチバイト対応していないのでstrrevのマルチバイト対応関数をmb_strrevとして作成してみます。
結果から先にお伝えするとマルチバイト対応パターン1での対応が良さそうでした。
マルチバイト非対応
PHP標準関数のstrrevはマルチバイト対応に対応していないためstrrevにマルチバイト文字列を使用すると文字化けします。
$str = 'https://hogehoge.jp/りんご/バナナ/山田太郎/';
echo(strrev($str));
結果
'/��㎃骤尔籱匀�/��⊃㊃㐃㝀�/��━㓂㊂㙀�/pj.egohegoh//:sptth'
マルチバイト対応パターン1
文字列を1文字ずつ配列化 -> 要素を逆順 -> 文字列化します。
$str = 'https://hogehoge.jp/りんご/バナナ/山田太郎/';
echo implode('', array_reverse(mb_str_split($str, 1, 'UTF-8')));
結果
'/」郎太田山「/”ナナバ”/’ごんり’/pj.egohegoh//:sptth'
マルチバイト対応パターン2
文字列を1文字ずつ配列化 -> 要素を逆順 -> 文字列化します。
$str = 'https://hogehoge.jp/りんご/バナナ/山田太郎/';
$length = mb_strlen($str, 'UTF-8');
$array = [];
for ($i = 0; $i < $length; $i++){
$text_string = mb_substr($str, $i, 1);
$array[] = $text_string;
}
echo implode('', array_reverse($array));
結果
'/郎太田山/ナナバ/ごんり/pj.egohegoh//:sptth'
パターン1とパターン2のパフォーマンスを比較
パターン1
$str = str_repeat('https://hogehoge.jp/りんご/バナナ/山田太郎/', 100);
for ($n = 0; $n < 10; $n++) {
$time_start = microtime(true);
$res = implode('', array_reverse(mb_str_split($str, 1, 'UTF-8')));
$time_end = microtime(true);
$time = $time_end - $time_start;
echo $time . "\n";
}
計測結果
0.00064992904663086
0.00030207633972168
0.00022697448730469
0.00016403198242188
0.00016188621520996
0.00016283988952637
0.00016283988952637
0.0001988410949707
0.00016283988952637
0.00016188621520996
パターン2
$str = str_repeat('https://hogehoge.jp/りんご/バナナ/山田太郎/', 100);
for ($n = 0; $n < 10; $n++) {
$time_start = microtime(true);
$length = mb_strlen($str, 'UTF-8');
$array = [];
for ($i = 0; $i < $length; $i++){
$text_string = mb_substr($str, $i, 1);
$array[] = $text_string;
}
$res = implode('', array_reverse($array));
$time_end = microtime(true);
$time = $time_end - $time_start;
echo $time . "\n";
}
計測結果
0.11650204658508
0.13163304328918
0.11916780471802
0.11850309371948
0.12335705757141
0.12020015716553
0.11864614486694
0.12817692756653
0.11864900588989
0.13683700561523
比較したところパターン1の方が数百倍程度パフォーマンスが良い結果となりました。
関数化
パフォーマンスの良かったパターン1をmb_strrevとして関数化して完了とします。
public static function mb_strrev(string $str, string $from_encoding): string //{{{
{
return implode('', array_reverse(mb_str_split($str, 1, $from_encoding)));
}