Looping through grapheme clusters:
<?php
// Example taken from Rust documentation: https://doc.rust-lang.org/book/ch08-02-strings.html#bytes-and-scalar-values-and-grapheme-clusters-oh-my
$str = "??????";
// Alternatively:
//$str = pack('C*', ...[224, 164, 168, 224, 164, 174, 224, 164, 184, 224, 165, 141, 224, 164, 164, 224, 165, 135]);
$next = 0;
$maxbytes = strlen($str);
var_dump($str);
while ($next < $maxbytes) {
$char = grapheme_extract($str, 1, GRAPHEME_EXTR_COUNT, $next, $next);
if (empty($char)) {
continue;
}
echo "{$char} - This utf8 character is " . strlen($char) . ' bytes long', PHP_EOL;
}
//string(18) "??????"
//? - This utf8 character is 3 bytes long
//? - This utf8 character is 3 bytes long
//?? - This utf8 character is 6 bytes long
//?? - This utf8 character is 6 bytes long
?>