PHP's strrev is not safe to use on utf-8 strings because it reverses a string one byte at a time. So if a character consists of multiple bytes it cannot be preserved as an entity in the reversed result.
There is no Multibyte String alternative to strrev
either.
We did some googling, but strangely enough all solutions we encountered were either invalid or incredibly heavy memory/code wise.
For example:
- using utf8_decode only works if your characters in the string exist in the ISO-8859-1 character set
- using preg_match_all seems weirdly over-engineered
- a simpler preg_match_all works, but on a 2MB string PHP was already using 150MB of memory. This is actually what sparked our search when when @renan_saddam noticed his PHP port of Github's email_reply_parser choked on a 2MB multibyte email.
What We Came Up With
Is dead simple, but I'm putting it online anyway since it's apparently not common good.
<?php
function mb_strrev ($string, $encoding = null) {
if ($encoding === null) {
$encoding = mb_detect_encoding($string);
}
$length = mb_strlen($string, $encoding);
$reversed = '';
while ($length-- > 0) {
$reversed .= mb_substr($string, $length, 1, $encoding);
}
return $reversed;
}
?>
Example:
<?php
echo strrev('Gonçalves') . "\n"; // returns sevla??noG
echo mb_strrev('Gonçalves') . "\n"; // returns sevlaçnoG
?>
In our tests, the above function was factor 5x more efficient in regards to memory consumption than the preg_match_all
solution.
Hope this helps