久しぶりにハマってしまいましたorz
調べても情報が少なくて少なくて。
「どうがんばっても動かない」なんてタイトルを付けましたが、最終的には動くようになったんだけど(๑´ڡ`๑)
ハマった時は一旦別なことをリフレッシュするのがいいね♪
半日はかかったかな、翌日に持ち越さなかったのは救い。
もしかしたら同じように困る人がいるかも知れない、と思いましたのでメモしておきます。
症状
トップページのみ、preg_match_all が動かない。
動かないというか、結果が表示されません。
特にエラーコードなどは出てないです。
1つのコードで全ページに適用されるものなのに、トップページだけ表示されない・・・。
という状態でした。
▼該当コード
preg_match_all('/<img [^>]*?src=(.+?).*?>/iu', $content, $imgs);
$content の中からimgタグを全て抽出してクラスを付与をさせるための preg_match_all です。
実はこのコードの中に問題があったんだけど、この時点で気付いたかな?
preg_match_all を preg_match に変えてもNG。
str_replace は問題なく動きました。
サーバー側の問題ではないのか?
調べると、そもそもサーバー側で preg_match を制御されることもあるらしい。
この記事によると、「pcre.backtrack_limit」というものでメモリに制限がかかっていたとあります。
なんだ、サーバーの問題だったのか、とわたしも pcre.backtrack_limit の値を上げてみたものの変化なし。
書き方や設置場所が悪いのかなと試行錯誤しましたが、よくよく考えるとトップページ以外では問題なく動作しているわけで。
なぜだ・・・、なぜトップページだけなんだ・・・。
preg_last_error() でエラーチェック
上述した記事でも試されていた方法です。
以下丸々使わせていただきました。
感謝。
if (preg_last_error() == PREG_NO_ERROR) {
print 'There is no error.';
}
else if (preg_last_error() == PREG_INTERNAL_ERROR) {
print 'There is an internal error!';
}
else if (preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR) {
print 'Backtrack limit was exhausted!';
}
else if (preg_last_error() == PREG_RECURSION_LIMIT_ERROR) {
print 'Recursion limit was exhausted!';
}
else if (preg_last_error() == PREG_BAD_UTF8_ERROR) {
print 'Bad UTF8 error!';
}
else if (preg_last_error() == PREG_BAD_UTF8_ERROR) {
print 'Bad UTF8 offset error!';
}
結果はというと・・・。
Bad UTF8 error!
えっ!文字コード!?
原因は修飾子だった
そうです、原因は文字コードで、preg_match_all の中で使用していた修飾子です。
修飾子とは、正規表現のデミリタの後に付ける、
- i
- u
- s
- m
とかです。
他にもいろいろあるので「正規表現 修飾子」などで検索してみてください。
で、上のコードに戻ります。
preg_match_all('/<img [^>]*?src=(.+?).*?>/iu', $content, $imgs);
ここで使われている修飾子の「u」は UTF-8 の「u」だったのです。
今までおまじないのように修飾子を付けていましたが、そのツケがここで回ってきたようです(*´ω`*)
なんで「u」を付けていたのか
う~ん、なんでだろ、PHPコードって毎回手打ちしないよね?
ある程度は過去に書いたコードを元に書き直したりするのが多いんだけど、それでかな。
修飾子は他にも「i」や「s」など、とりあえず付けてることも多かったり(汗
正規表現の文字コードについては、特に指定が無ければソース中の文字コードが適応されるらしい。
ってことは「u」を付けることの方がイレギュラーってことになるのか( ..)φ
トップページだけ動かなかったのは、トップページ文字コードがおかしなことになっていたんだろうね。
あとがき
preg_last_error() でエラーチェックをした時、最初は「There is no error.」でエラーは出ませんでした。
何でかというと、preg_last_error() を書く位置が悪かったので(>_<)
該当の preg_match_all の下に書かなければならないのに、上の方に書いてた。
あ、今更だけど、preg_last_error() は preg_match でも preg_match_all でもチェックできます。
あとあれだね、ハマった時は一旦別のことした方がいいね。
お風呂入ったり昼寝したり。
経験上の話だけど、PCの前で考えるよりも寝たり湯船につかったりしながら考えた方が、気付けることが多いと思う。