WordPressプラグインを改造していてMySQLの文字コードにはまる
日本語化されていない、WordPressプラグインを、日本語化して使おうとしています。今回、MySQLのデータベースのテーブルの列の文字コードの設定が、utf8ではなくlatin1になっていて、かなりはまりました。
VCCW環境を使って作業できるので、とても楽です。
- VCCWでWordPressプラグインの開発環境を構築 : プラスα空間 (2015年6月17日)
国際化にきちんと対応されたプラグインだと、potファイルを元にpo/moファイルを作るだけなので、簡単です。ところがこのプラグインは、
potファイルも無いし、国際化のための文字列の切り出しも中途半端です。かなり修正しました。potファイルを作るのは、次の方法でできます。
VCCW環境内では、xgettextがあらかじめインストールされているので簡単です。
[vagrant@vccw ~]$ cd /var/www/wordpress/wp-content/plugins/pluginname/ [vagrant@vccw ~]$ xgettext --language=php --keyword=__ --keyword=_e --keyword=_n:1,2 --keyword=_x -o languages/pluginname.pot *.php */*.php
こうやって作成した、日本語化のためのローカライズファイル(po/mo)を読み込むための定番は、次の通りです。最初この記述をどこに入れれば良いかで、かなり悩みました。試行錯誤の上、プラグインの先頭に入れるだけでした。当たり前ですね。
$path = dirname(plugin_basename( __FILE__ )) . '/languages';
load_plugin_textdomain( 'pluginname', false, $path);
このやり方は、私も持っている次の本に載っています。
[amazonjs asin="B00M939Y0I" locale="JP"]この設定の末、日本語化の道筋が見えました。
このプラグインで、Webから取得したデータをキャッシュしておく機能があります。キャッシュされてい無い状態では表示が文字化けしないのですが、キャッシュされた2回目以降のアクセスでは、文字化けします。
プラグイン内部で、var_dump()して、どこで文字化けするかを探しました。その結果、取得したデータを、MySQLに保存するところが怪しいことがわかりました。
必死に検索して、次の記事がヒントになりました。
VCCWのWordPressデータベースは、次の設定になっています。
% vagrant ssh Last login: Sat Jul 11 08:16:16 2015 from 10.0.2.2 ___ ___ ___ ___ / /\ / /\ /__/\ /__/\ / /:/ / /:/ _\_ \:\ \ \:\ / /:/ / /:/ /__/\ \:\ \ \:\ / /:/ ___ / /:/ ___ _\_ \:\ \:\ ___ \__\:\ /__/:/ / /\ /__/:/ / /\ /__/\ \:\ \:\ /__/\ | |:| \ \:\ / /:/ \ \:\ / /:/ \ \:\ \:\/:/ \ \:\| |:| \ \:\ /:/ \ \:\ /:/ \ \:\ \::/ \ \:\__|:| \ \:\/:/ \ \:\/:/ \ \:\/:/ \__\::::/ \ \::/ \ \::/ \ \::/ ~~~~ \__\/ \__\/ \__\/ http://vccw.cc/ Initial code by Takayuki Miyauchi. https://github.com/miya0001 [vagrant@vccw ~]$ egrep 'DB_' /var/www/wordpress/wp-config.php define('DB_NAME', 'wordpress'); define('DB_USER', 'wordpress'); define('DB_PASSWORD', 'wordpress'); define('DB_HOST', 'localhost'); define('DB_CHARSET', 'utf8'); define('DB_COLLATE', '');
直接、MySQLにつないで、データベースを確認します。
[vagrant@vccw wordpress]$ mysql -u wordpress -p Enter password: wordpress Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 604 Server version: 5.5.43-log MySQL Community Server (GPL) by Remi Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | test | | wordpress | +--------------------+ 3 rows in set (0.00 sec) mysql> use wordpress Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed
ちゃんと"wordpress"データベースがありました。直接、テーブルにデータを挿入します。まずは、ASCIIだけのデータを挿入します。
mysql> insert into wp_pluginname (URL, body, updated) values ("AAA", "AAA", NOW()); Query OK, 1 row affected (0.01 sec) mysql> select * from wp_pluginname; +----------+----------------------------------------+---------------------+--------+ | Cache_id | URL | updated | body | +----------+----------------------------------------+---------------------+--------+ | 10 | AAA | 2015-07-11 08:23:34 | AAA | +----------+----------------------------------------+---------------------+--------+ 1 rows in set (0.00 sec)
問題なく、挿入できました。次は、日本語を含んだデータを挿入します。
mysql> insert into wp_pluginname (URL, body, updated) values ("BBB", "BBBいいい", NOW()); Query OK, 1 row affected, 1 warning (0.00 sec) mysql> select * from wp_pluginname; +----------+----------------------------------------+---------------------+--------+ | Cache_id | URL | updated | body | +----------+----------------------------------------+---------------------+--------+ | 10 | AAA | 2015-07-11 08:23:34 | AAA | | 11 | BBB | 2015-07-11 08:24:09 | BBB??? | +----------+----------------------------------------+---------------------+--------+ 2 rows in set (0.00 sec)
げげっ! 化けてる。WordPressの問題ではなく、MySQLのデータベースが何かおかしいです。設定されている文字コードを表示させてみます。
mysql> show variables like 'char%'; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+ 8 rows in set (0.01 sec) mysql> show create table wp_pluginname; +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | wp_pluginname | CREATE TABLE `wp_pluginname` ( `Cache_id` int(10) NOT NULL AUTO_INCREMENT, `URL` text NOT NULL, `updated` datetime DEFAULT NULL, `body` longtext CHARACTER SET latin1, PRIMARY KEY (`Cache_id`), UNIQUE KEY `URL` (`URL`(255)), KEY `Updated` (`updated`) ) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 | +----------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
データベースそのものはutf8になっているけど、wp_pluginnameと言うテーブルの文字コードが"latin1″になっている! これが原因だ〜!! プラグインのコード内で、文字コードを設定する部分も発見できました。やはり、latin1に設定しています。
$alterSQL = "ALTER TABLE `{$table}` CHANGE `body` `body` LONGTEXT CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL;";
文字コードを、utf8に変更します。
mysql> ALTER TABLE wp_pluginname CHANGE `body` `body` LONGTEXT CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL; Query OK, 0 rows affected (0.00 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> show create table wp_pluginname; +----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | wp_pluginname | CREATE TABLE `wp_pluginname` ( `Cache_id` int(10) NOT NULL AUTO_INCREMENT, `URL` text NOT NULL, `updated` datetime DEFAULT NULL, `body` longtext, PRIMARY KEY (`Cache_id`), UNIQUE KEY `URL` (`URL`(255)), KEY `Updated` (`updated`) ) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 | +----------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
utf8になったっぽいです。データを挿入してみます。
mysql> insert into wp_pluginname (URL, body, updated) values ("CCC", "CCCううう", NOW()); Query OK, 1 row affected (0.00 sec) mysql> select * from wp_pluginname; +----------+----------------------------------------+---------------------+--------------+ | Cache_id | URL | updated | body | +----------+----------------------------------------+---------------------+--------------+ | 10 | AAA | 2015-07-11 08:23:34 | AAA | | 11 | BBB | 2015-07-11 08:24:09 | BBB??? | | 12 | CCC | 2015-07-11 08:33:49 | CCCううう | +----------+----------------------------------------+---------------------+--------------+ 3 rows in set (0.00 sec)
やりました! ちゃんと、日本語が保存されています。この後、実際のプラグイン操作で、文字化けし無いことを確認しました。MySQLのデータベースに文字コードの設定があったのは知っていましたが、まさかテーブルの文字コードを個別に変更できるとは!! 正確には、テーブルよりもっと細かい、列のレベルで文字コードの設定ができます。
この問題を解決するまで、かなりの時間がかかりました。
ディスカッション
コメント一覧
まだ、コメントがありません