PHPをバージョンアップしたらMySQLに登録されるUTF-8文字列がエスケープされちゃって困った。

ニッチな話Easy APNSとEasyAPNSPanelってゆーのを使ってiOSアプリのPush通知をしていたんだけど、そのサーバにWordpressを入れようとしたらPHPのバージョンが4.1だとかでWordpress入れらんないよと怒られたもんで、あれこれ時間をかけサーバを落っことしてサービスをこっそり止めながらPHPとMySQLをバージョンアップしたのです。この辺を参考に
http://temog.info/archives/vps/serversmanvps-php5-3-2-mysql5-1-45-のインストール.html

そしたらEasy APNSがダメダメになって方々から「送れねー!」「おくれねー!」と怒られまして、いろいろまた時間をかけてサーバを落っことしてサービスをこっそり止めながらあれやこれや試行錯誤をしたのです。

まず、PHPMySQLで確認するとapns_messagesテーブルのmessagesフィールドが途中でちょんぎれてしまってる。なんかバージョンアップ前のフィールドにはUTF-8の文字がそのまま入ってて日本語読めるぞーだったのに、”\u3066\u3059\u3068\”みたいに文字化けしてるわけ。
これが一週間くらいかかって文字化けじゃなくてUTF-8文字が16進数にエスケープされてるという状態らしいよ?なにそれそんなこと勝手にやらないでくれる?迷惑だから。

というわけでmessageフィールドをVARCHAR(255)からVARCHAR(1024)にしてこれで入ったじゃんええやろ文字化けしててもちゃんとAPNS送信するときUTF-8の元の文字に戻ってるし・・・と思ったら今度はまた「送れねー」とLINEで叩き起こされてエラーログを見てみると、

 

PHP Notice:  APNS responded with command(8) status(8) pid(43633).

	1) APNS::__construct -> File: apns.php (line 51)
	2) APNS::_fetchMessages -> File: class_APNS.php (line 244)
	3) APNS::_iterateMessages -> File: class_APNS.php (line 419)
	4) APNS::_pushMessage -> File: class_APNS.php (line 472)
	5) APNS::_triggerError -> File: class_APNS.php (line 600)

 in /var/www/html/zoupush/classes/class_APNS.php on line 708
PHP Fatal error:  APNS responded with error for pid(43633). status(8: Invalid token)

	1) APNS::__construct -> File: apns.php (line 51)
	2) APNS::_fetchMessages -> File: class_APNS.php (line 244)
	3) APNS::_iterateMessages -> File: class_APNS.php (line 419)
	4) APNS::_pushMessage -> File: class_APNS.php (line 472)
	5) APNS::_triggerError -> File: class_APNS.php (line 606)

 in /var/www/html/zoupush/dontcomp/classes/class_APNS.php on line 708

 

と表示されている。これはプッシュするメッセージが長いよとApple様から怒られている状態である。もういろんなところから怒られっぱなしや・・・。
どうやらエスケープしたまんまのUTF-8を受け取ってるみたい。そりゃ一文字が”\u3066″とかになったら長くなるよな。というわけでMySQLのデータベースに登録されるときに勝手にUTF-8をエスケープしないようにどこでそんなことをやっちまってるのかを探し出さないといけない。

まずは疑ってみるのは/etc/php.iniと/etc/my.cnf。

 

my.cnf
default-character-set=utf8
character-set-server=utf8

php.ini
default_charset = “UTF-8″
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.http_input = auto
mbstring.http_input = UTF-8
mbstring.http_output = UTF-8
magic_quotes_gpc = Off

 

とかいろいろとまた時間をかけてサーバを落っことしてサービスをこっそり止めながらあれやこれや試行錯誤をしたのです。
 

直らねーーー!!!!

 
しゃーないから、
/include/sendPush.php
/classes/class_APNS.php
のPHPコードを追いましたよ、ええ。一行一行、メッセージを変数に入れたり、エンコードしたりするところでfopenでwしてtmp.txtに出力したりして、とてもとても時間かかりましたよ、ええ。

UTF-8文字をどっかでエスケープしてるんです。pack(“*H”,$message)とかやってるんだと思ってました、探したらけど見つからない、どーにもやってない。
そしたら

 

$message = $this->_jsonEncode($usermessage);

 

ていうとこで、エスケープされてることに気付きました。
そこでこのメソッドを見ると

 

	private function _jsonEncode($array=false){
		//Using json_encode if exists
		if(function_exists('json_encode')){
			return json_encode($array);
		}

 

うおおお・・・。
いろいろ調べたら分かったのですが、json_encodeという関数はPHP5から使えるようになったらしいです。さらにPHP5.4からjson_encodeにオプションが設定できるようにもなったとか。
でいろいろ調べたら、旧バージョンではPHP4.1とかだったもので、json_encodeは使えず御丁寧に自前で書いた_jsonEncodeでjsonEncodeしていて、PHPバージョンアップしたら5.4になったもんだからjson_encodeを晴れて使えるようになったけど
 

マルチバイト文字をデフォルトでエスケープしやがる!!!

 
だったのです。
というわけで、結論
return json_encode($array);

return json_encode($array, JSON_UNESCAPED_UNICODE);
に変えただけで直った。。。
おおう・・・たった一行、しかもオプション指定しただけやで・・・・。
この一週間なんだったんだ。
 

サーバ設定大嫌い。

 
以上!

・・・ともう一台のサーバでも同じ一行直すやつやったら、PHP5.3でアンエスケープできないでやんの!!!もうーというわけでこっちは

 

//		if(function_exists('json_encode')){
//			return json_encode($array, JSON_UNESCAPED_UNICODE);
//		}

 

とコメントアウトして逃亡!

ほんとに以上!

PHPをバージョンアップしたらMySQLに登録されるUTF-8文字列がエスケープされちゃって困った。
トップへ戻る