半角スペースの影響でstr_replace関数が動かなかった時の対応

PHP

管理画面にWYSIWYG(ブログやwebメールで使われるようなエディターです。ウィジウィグと呼ばれます。)の機能をつけて開発していますが、特定のタグに関して更新ボタンを押下することでタグを丸ごと置換したい、というタスクがありました💪

言語はPHP(Laravel)を使っていて、str_replace関数を使って入れ替えをしようとしましたが、うまく関数が効かなかった時の内容と対応を記しています📝

今回の内容は、PHP以外の言語でも同様のケースが起こり得て、参考になるかもしれません👀

PHPのstr_replace関数について簡単に説明すると、特定の文字列を入れ替えできる関数です。

公式引用しますが、それぞれの引数の横に、意味を自分の言葉で書いてみました。

PHP: str_replace - Manual
str_replace(
array|string $search, //①:③の中で、具体的に置換したい文字列の箇所(beforeのもの)
array|string $replace, //②:①の代わりとして、置換したい文字列(afterのもの)
string|array $subject, //③:もともとの対象の文字列一式
int &$count = null   //(オプション)置き換えられた回数をここに格納
): string|array

今回のケースだと、コードは以下のような感じでした。

$changeTag = "<div class=\"bbb\"> </div>";
$search = "<div class=\"aaa\"> </div>";

$contents = 
 str_replace(
  $search,
  $changeTag,
  $html //静的ページのコードが格納
 );

$html には静的ページのコードがまるっと格納されてるのですが、その中には
<div class=\"aaa\"> </div>
の箇所があって、それを
<div class=\"bbb\"> </div>
というタグに変更したい、ということがやりたいことです。

このように、divタグで囲った箇所を入れ替えしようとしましたが、なぜかstr_replaceが機能しませんでした。
エラーが起きているわけではないので、第2引数はいいとして、第1引数の$searchのところで検索が引っかかってないからっぽいです。。

str_replace関数をかける手前のところでdd($search,$changeTag,$html);を使って止めてみて、$search,$changeTag,$htmlの中をそれぞれ見てみましょう。

※今回のキャプチャ画像小さくてすみません!拡大してみてください🙇‍♂️

変数の中をみてみても差分ツールで比較しても文字にはtypoがなく、「一致してるのに一致していない」という状態に。なぜだ。。。🤔

色々試しましたが、<div class=\"aaa\">だけであれば検知して置換できるので、半角スペースかdivのとじタグどちらかが一致していないということになりますが、半角スペースが怪しいのでは?と思いました。

そして、この事象は、文字コードと何か関係があるのでは?と思いました。

同じ箇所のところで、今度はdd(json_encode($search,$changeTag,$html));でデバッグしてみます👨‍💻

なお、json_encode()でJSON形式の文字列、Unicodeエスケープシーケンスに変換された状態にしてくれるそうで、Unicodeエスケープシーケンスとは、UTF-16という文字符号だそうです・・・(この辺りの知識がまだ未熟です)

dd(json_encode($search,$changeTag,$html));した結果 
※コードはまだ何も変えてません

差分があったーー!
確かにstr_replace関数の第1引数にはないものに、第3引数では何かありますね!

第3引数の変数のdivタグの間に、普通のdd();では見えなかった\u00a0がありました!
この「(json_encodeを使うと見えるけど普通の時には見えなかった」\u00a0を$search変数のdivタグの間に記述しました。

$search = "<div class=\"aaa\">\u00a0</div>";

もう一度、dd(json_encode($search,$changeTag,$html))をしてみると、、、
$search変数にも見えています! これで一致していることを確認しました!

動かしてみると、、
無事置換されました!!やったーー!🙌(画像撮り忘れた。。。😭)

半角スペースとなると、 “&nbsp;“のイメージがあったので、\u00a0って何?と思いました。

少し調べましたが、UTF-16という文字符号で表す空白の一つみたいです
元々は普通の半角スペースだったものが、どこかでこちらに変換されているということでしょうか・・・?

また調べていて驚いたのは、空白といってもたくさん種類がある、ということです
例えば、\u0020というのも存在します。奥深いですね、、、

まとめです

もし文字列を置換(今回の場合はPHPのstr_replace関数でした)をしようとして、
文字列はあっているのに、想定通りに動作されない場合は以下を試してみてください👨‍💻

1. json_encode()で中身を確認してみてください!

2. もし差分があったら差分のところ(今回でいうと、文字符号のところですね)を調整してみてください!

そうすればうまく解決するかもしれません!

コメント

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