LoginSignup
2
5

More than 3 years have passed since last update.

結合文字列(合成文字)の濁点/半濁点をどうにかする(PHP)

Last updated at Posted at 2020-08-22

この2つの違いはなんでしょうか

1.ポセイドン
2.ポセイドン

見た目は同じだけど…

経緯

スクレイピングで取得した文字列を画像に出力するシステムを作っている時のこと
なんか出力結果がおかしい
スクリーンショット 1.png

「ポセイドン」と綺麗に出力したいのに濁点と半濁点が分離した「ホ゜セイト゛ン」となってしまう。
もし読み込ませているデータ自体が「ホ゜セイト゛ン」ならわかるけど

読み込み先の文字列を見てみると「ポセイドン」…なぜだ

Unicodeによる結合

どうやら2文字のデータを1文字に纏める結合というものが行われていて、特に今回スクレイピングみたいにwebからごちゃごちゃ取ってきたりすると混同しがちらしい。

どういう理屈で混同してるのかとか、なぜこんなものが生まれてしまったのかはさておき、とりあえずこの「ポセイドン」を「ポセイドン」にしたい。

とりあえず文字コード見てみよう

poseidon.php
<?php
$poseidon = "ポセイドン";

$moji_code = substr(json_encode($poseidon), 1, -1);

echo $moji_code;

出力結果
\u30db\u309a\u30bb\u30a4\u30c8\u3099\u30f3

てことはつまり

\u30db\u309a => ホ + 半濁点
\u30c8\u3099 => ト + 濁点

ということで「\u309a」(半濁点)と「\u3099」(濁点)をこの状態で置換してjson_decode()すればよさそう。
かといって「ホ」(\u30db)を直で「ポ」(\30ddらしい)に直で変えるのはすごく面倒なので
mb_convert_kana()のKとVオプションを使って元に(?)戻す。
こいつを使えば、「ポセイドン」 => 「ポセイドン」に変換できる。つまり「゚」と「゙」に置換できればオーケー。

順序としては

①結合文字列を文字コードで出して
②「\u309a」(結合文字の半濁点)を「\u309c」に、「\u3099」(結合文字の濁点)を「\u309b」に置換
③デコードして
④全角カナを半角カナにして(ホ゜セイト゛ン => ポセイドン)
⑤濁点付き半角カナを全角カナに変換(ポセイドン => ポセイドン)

でいけそう

poseidon.php
<?php
$poseidon = "ポセイドン";
//①
$moji_code = substr(json_encode($poseidon), 1, -1);

//②
$moji_code = str_replace("\u3099",'\u309b',$moji_code);
$moji_code = str_replace("\u309a",'\u309c',$moji_code);

//③
$decode_poseidon = json_decode(sprintf('"%s"', $moji_code));

//④
$decode_poseidon = mb_convert_kana($decode_poseidon,"aks","utf-8");

//⑤
$decode_poseidon = mb_convert_kana($decode_poseidon,"KV","utf-8");

echo $decode_poseidon;

気になる結果は…

出力結果
ポセイドン

いやわからんわ。画像で出力して確認する

スクリーンショット 2.png

やったーーーーーー!!!

感想

こんな地味なのがqiita初投稿になるなんて

ちなみになぜポセイドンなのかというと、濁点と半濁点を含む1単語がこれ以外「パリピギャル」くらいしか思い浮かばなかったからです。

最後まで読んでいただきありがとうございました。

8/25 追記

コメントでNormalizerクラスを使うと1行で済むことをご教授頂きました。
誠にありがとうございます。無知を恥じるばかりです。

2
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5