PHP Tips | 文字列処理:入力補助 - 絵文字除去

PHP PHP
スポンサーリンク

何をしたいユーティリティなのか

「絵文字除去」は、その名の通り、 ユーザーが入力したテキストから「絵文字だけ」を取り除くためのユーティリティです。

スマホからの入力だと、文章の中に自然に絵文字が混ざります。

「今日は楽しかったです😊」 「承知しました👍」

人間的にはうれしいんですが、業務システム的には困ることが多いです。

ログに文字化けしたり、 古い DB が絵文字を保存できなかったり、 外部システムに送るときにエラーになったり。

そこで、「絵文字だけを削って、残りのテキストはそのまま使う」ためのユーティリティを用意しておくと、実務がかなり安定します。

絵文字がやっかいな理由をざっくり知る

絵文字は「普通の 1 文字」じゃないことが多い

絵文字は、ざっくり言うと「特殊な Unicode のコードポイント」です。 しかも、1 個の絵文字が「複数のコードポイントの組み合わせ」で表現されることもあります。

例えば、 肌の色付きの手の絵文字や、 家族の絵文字(👨‍👩‍👧‍👦)などは、 複数の文字を「ゼロ幅ジョインナー」でつないだものです。

つまり、「1 文字ずつ見て判定する」のがけっこう難しい世界なんです。

現実的なアプローチ:「絵文字っぽい領域をまとめて削る」

Unicode の「絵文字が多い範囲」をざっくり指定する

厳密に「すべての絵文字」を判定するのはかなり大変なので、 実務では「絵文字が多く含まれる Unicode の範囲」をざっくり指定して削る、というアプローチがよく使われます。

PHP では、preg_replace と Unicode フラグ(u)を使って、 「この範囲の文字を全部消す」ということができます。

例えば、次のような範囲は、絵文字がたくさん含まれています。

  • \x{1F300}\x{1F5FF} … 天気、場所、物など
  • \x{1F600}\x{1F64F} … 顔文字(スマイル系)
  • \x{1F680}\x{1F6FF} … 乗り物、地図記号など
  • \x{2600}\x{26FF} … 一部の記号・絵文字
  • \x{2700}\x{27BF} … その他の記号

これらをまとめて「削除対象」にしてしまう、という方針です。

実装例:絵文字をざっくり削除する関数

コアとなる絵文字除去ユーティリティ

/**
 * 文字列から「絵文字っぽい文字」をざっくり削除する
 *
 * 完全に厳密ではないが、実務で困ることが多い絵文字をだいたい落とす。
 */
function remove_emojis(string $text): string
{
    // 絵文字が多く含まれる Unicode の範囲をまとめて削除
    $pattern = '/['
        . '\x{1F300}-\x{1F5FF}'  // Miscellaneous Symbols and Pictographs
        . '\x{1F600}-\x{1F64F}'  // Emoticons
        . '\x{1F680}-\x{1F6FF}'  // Transport and Map Symbols
        . '\x{2600}-\x{26FF}'    // Miscellaneous Symbols
        . '\x{2700}-\x{27BF}'    // Dingbats
        . ']/u';

    return preg_replace($pattern, '', $text) ?? $text;
}
PHP

ここでの重要ポイントは、「/u フラグを付けている」ことです。 u を付けることで、正規表現が「UTF-8 の Unicode コードポイント」として文字を扱ってくれます。

例題で挙動を確認する

シンプルな絵文字入りテキスト

$text = '今日は楽しかったです😊 ありがとう👍';

echo remove_emojis($text);
PHP

出力はこうなります。

text

今日は楽しかったです ありがとう

絵文字だけが削られ、 日本語の文章はそのまま残っています。

絵文字と記号が混ざる場合

$text = 'OKです!😊 ※注意事項をよく読んでください。';

echo remove_emojis($text);
PHP

出力はこうです。

text

OKです! ※注意事項をよく読んでください。

「※」のような普通の記号は残り、 絵文字だけが削られています。

実務での使いどころ

古い DB に保存するときの前処理

古い MySQL(utf8mb4 ではない utf8)などは、 絵文字を保存しようとするとエラーになったり、文字化けしたりします。

その場合、「保存前に絵文字を削る」という前処理を入れておくと安全です。

$rawComment = $_POST['comment'] ?? '';

$comment = remove_emojis($rawComment);

// ここで DB に保存
PHP

ユーザーの文章はほぼそのまま残りつつ、 「保存できない文字」だけを落とせます。

外部システムに送るときのクリーニング

外部 API が「絵文字を受け付けない」仕様になっていることもあります。 その場合も同じように、送信前に絵文字を削ります。

$payload = [
    'message' => remove_emojis($rawMessage),
];

$client->post('/send', $payload);
PHP

「絵文字が原因で API がエラーになる」という事故を防げます。

もう一歩:絵文字を「別の記号に置き換える」版

完全に消すのではなく、痕跡を残したい場合

「絵文字があったこと自体は残しておきたい」という場合もあります。 そのときは、「削除」ではなく「置換」にします。

function replace_emojis_with_marker(string $text, string $marker = ''): string
{
    $pattern = '/['
        . '\x{1F300}-\x{1F5FF}'
        . '\x{1F600}-\x{1F64F}'
        . '\x{1F680}-\x{1F6FF}'
        . '\x{2600}-\x{26FF}'
        . '\x{2700}-\x{27BF}'
        . ']/u';

    return preg_replace($pattern, $marker, $text) ?? $text;
}
PHP

例えば、$marker = '[emoji]' としておけば、

$text = '今日は楽しかったです😊';

echo replace_emojis_with_marker($text, '[emoji]');
PHP

出力はこうなります。

text

今日は楽しかったです[emoji]

「ここに絵文字があった」という情報だけは残せます。

絵文字除去の限界と割り切り

「完璧」を目指しすぎないことも大事

正直に言うと、「すべての絵文字を完全に正しく判定して削る」のはかなり難しいです。 新しい絵文字はどんどん追加されますし、 複数コードポイントの組み合わせも増えています。

実務では、

「よく使われる絵文字の大部分を落とせれば十分」 「もし漏れがあっても、致命的な問題にはなりにくい」

という割り切りで設計することが多いです。

今回のような「絵文字が多い範囲をざっくり削る」ユーティリティは、 その現実的な落としどころの一つです。

まとめ:今日からの「絵文字除去」ユーティリティ

絵文字除去の本質は、「人間にはうれしい絵文字を、システム的には安全な形にする」ことです。

そのために、

絵文字が多く含まれる Unicode の範囲を正規表現で指定する。 preg_replaceu フラグで、その範囲の文字を削除する。 必要なら削除ではなく、マーカー文字に置き換える。

という処理を 1 本の関数に閉じ込めておきます。

もう一度、基本形を載せておきます。

function remove_emojis(string $text): string
{
    $pattern = '/['
        . '\x{1F300}-\x{1F5FF}'
        . '\x{1F600}-\x{1F64F}'
        . '\x{1F680}-\x{1F6FF}'
        . '\x{2600}-\x{26FF}'
        . '\x{2700}-\x{27BF}'
        . ']/u';

    return preg_replace($pattern, '', $text) ?? $text;
}
PHP

もし、あなたのシステムで「絵文字が原因の文字化けやエラー」が起きているなら、 その入力経路のどこかに、このユーティリティを一段かませてみてください。 ユーザーの文章の“温度感”は少し下がるかもしれないけれど、 システムの安定感は、確実に一段上がります。

タイトルとURLをコピーしました