【解決】MySQLでselectしたら日本語が文字化けしてしまった場合の対処法

2021年10月18日

mysql selectしたら日本語が文字化けの対処法

先日、作成していたWebアプリケーションにおいて、phpMyAdmin上では全角文字もすべて正常に文字化けせずに見えているのに、MySQLのselectをphpから実行して表示した際に、全角文字がすべて「?」になってしまう事象が発生しました。

今回は、そんな場合にどのように対処したらよいかをお伝えします。

【結論】SET NAMES utf8 を実行する

悩んでいたときの状況

DBのテーブルには、3万冊ほどの図書データが格納されていて、それらのレコードには図書名、著者や出版社・出版年のデータがカラムとしてありました。

照合順序は「utf8_general_ci」です。

出版年は数字ですし、海外の図書の場合は半角英数のみ使われているので問題はないのですが、国内の図書に関しては、図書名や著者、出版社の部分は当然日本語です。

phpMyAdminにてそのテーブルを見てみると、問題なく全角文字もしっかりと表示されていましたが、組み上げた図書検索システムのphpを介してページに表示すると、全角文字がすべて「?」になっていました。

DBへの接続はPDOを用いて行っており、その際にも「charset=utf8」と指定していたので、なぜ照合順序もutf8なのに文字化けしてしまうのか非常に不思議で悩みに悩んでいました。

その際のコードは下記のとおりです。

try {
	// MySQLへの接続
	$dsn = "mysql:host=" . $host . ";dbname=" . $dbname . ";charser=utf8";
	$pdo = new PDO($dsn, $username, $password);
	$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
	$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) { // PDOExceptionをキャッチする
	print $e->getMessage() . "<br/gt;";
	die();
}

たった少しのコードで解決

そこで調べていくと、同じような問題にぶち当たっていた方を発見し、その方が試した方法を実行したところ一発で直ってしまいました!

感謝!

成功したコードは下記のとおりです。

7行目の$stm = $pdo -> query(“SET NAMES utf8;");を追加しただけです。

try {
	// MySQLへの接続
	$dsn = "mysql:host=" . $host . ";dbname=" . $dbname . ";charser=utf8";
	$pdo = new PDO($dsn, $username, $password);
	$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
	$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
	$stm = $pdo -> query("SET NAMES utf8;");
} catch (PDOException $e) { // PDOExceptionをキャッチする
	print $e->getMessage() . "<br/gt;";
	die();
}

SET NAMESとは何か?

SET NAMES は、クライアントからサーバーへの SQL ステートメントの送信に使用される文字セットを示します。したがって、SET NAMES 'cp1251’ は、「このクライアントから今後受信するメッセージが文字セット cp1251 で送信される」ことを、サーバーに知らせます。
出典:https://dev.mysql.com/doc/refman/5.6/ja/charset-connection.html

これから送る命令がどんな文字セットで構成されているのか、知らせる必要があるようですね。