PHP 8.4でgrapheme_str_split関数を追加しました #phpcondo
TOP > てきとうにこらむ > ゲーム作りとプログラミング日記 > PHP 8.4でgrapheme_str_split関数を追加しました #phpcondo
grapheme_str_split関数を追加しました
「str_split、そういえば書記素クラスター単位のstr_splitないよな?」とPHPカンファレンス北海道2024で発表資料を作って気付いてから4ヶ月。ついにgrapheme_str_split関数がmasterブランチにマージされ、日の目を見ました。
https://wiki.php.net/rfc/grapheme_str_split
概要
書記素クラスターとはなにか?というところから話をしなければいけませんが、例えばこの🙇♂️男性が土下座をしている絵文字は、1文字に見えると思います。 見えなかったらお使いのデバイスのOSか何かが古すぎます。この、「1文字に見える」というものを「書記素クラスター(Grapheme cluster)」と呼んでいます。
しかし、実は🙇♂️はコードポイント(Unicodeのコードポイント)単位では4つのコードポイントで構成されています。mb_str_splitをすればそれがなにの意味をなしているのかわかります。
$ sapi/cli/php -r 'var_dump(mb_str_split("🙇♂️"));'
array(4) {
[0]=>
string(4) "🙇"
[1]=>
string(3) "" // U+200D Zero Width Joinner
[2]=>
string(3) "♂"
[3]=>
string(3) "️" // U+FE0F VARIATION SELECTOR
}
これではstr_splitできないじゃん!と気付いたといいますか、そもそもGrapheme関数の内容が少なすぎると感じました。 したがって、少なくともstr_split出来たほうがよくない?ということでgrapheme_str_splitを作るという運びになりました。
なお、他の言語では大体書記素クラスター単位で処理できるようにはなっていて、Rubyでは String#grapheme_clusters があります。
使い方
function grapheme_str_split(string $string, int $length = 1): array|false {}
使用例
$ sapi/cli/php -r 'var_dump(grapheme_str_split("👨🏻❤️💋👨🏾👩❤️👩"));'
array(2) {
[0]=>
string(35) "👨🏻❤️💋👨🏾"
[1]=>
string(20) "👩❤️👩"
}
$stringにはUTF-8のみ許可しています。$lengthには配列の1要素に何文字いれる?というものです。内部で処理に失敗することがある場合にfalseが返ります。通常は配列が返ってきます。 Intl拡張なので --enable-intl でいれることをお忘れなく。
感想
このRFCは結構人気だったっぽくて、最終的には19票のYesをいただきました。それだけUnicodeに興味を持ってもらえたのは幸いだったと思います。また、ここでは述べていませんが、異体字セレクタにも適用できるわけですが、漢字の異体字セレクタだけでは難しかったかもしれません。絵文字ありがとう。