零弐壱蜂

[WordPress] 絵文字(Unicode6.0)が使えない問題

WordPress 4.2 より「拡張文字のサポート」として中国語・日本語・韓国語の文字、音楽・数学用の記号、象形文字を含む多くの新しい文字に対応しました。
この記事で紹介しているDBのテーブルの文字コードを変えるという手法もアップデートの流れで行われているようです。

CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

デフォルトで絵文字?が使えるようになったみたいです。


詳しい経緯は省きますが、2010年に Unicode6.0 に絵文字が登録され、ケータイでおなじみのの絵文字をPCでも閲覧できるようになりました。(環境によっては見られない場合があります)

詳細: 顔文字 – Wikipedia

Twitterなんかでは環境依存文字何それ世代が頻繁にこれらの文字を使ってるのを散見されます。見られる環境が一般的になっていけば使っても何ら問題はありません。今後、私も使っていきたいと思っています。

以前、仕事でこの絵文字(Unicode6.0)がデータベースに登録できない問題がありました。それはWordPressでも発生しうる問題で、検証してみると見事に発生したので、今回はその問題と対処法について書きたいと思います。

WordPressで絵文字(Unicode6.0)は使えるのか

結論から述べますと使えません

環境がある方は試しにこちらから絵文字を適当にコピペして記事を投稿してみてください。
おそらく、絵文字の部分が空になっているはずです。

WordPressの投稿画面で絵文字を入力した図

なぜ使えないのか

簡単に言うと、使用するテーブルのCHARSETに問題があります。

WordPressのデータベースを確認するとCHARSETutf8となっています。

mysql> SHOW CREATE DATABASE wp;
+----------+-------------------------------------------------------------+
| Database | Create Database                                             |
+----------+-------------------------------------------------------------+
| wp       | CREATE DATABASE `wp` /*!40100 DEFAULT CHARACTER SET utf8; */ |
+----------+-------------------------------------------------------------+
1 row in set (0.00 sec)

また、記事の登録されるテーブルも確認するとCHARSETutf8となっています。

mysql> show create table wp_posts \G
*************************** 1. row ***************************
       Table: wp_posts
Create Table: CREATE TABLE `wp_posts` (
  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `post_author` bigint(20) unsigned NOT NULL DEFAULT '0',
  `post_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `post_date_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `post_content` longtext NOT NULL,
  `post_title` text NOT NULL,
  `post_excerpt` text NOT NULL,
  `post_status` varchar(20) NOT NULL DEFAULT 'publish',
  `comment_status` varchar(20) NOT NULL DEFAULT 'open',
  `ping_status` varchar(20) NOT NULL DEFAULT 'open',
  `post_password` varchar(20) NOT NULL DEFAULT '',
  `post_name` varchar(200) NOT NULL DEFAULT '',
  `to_ping` text NOT NULL,
  `pinged` text NOT NULL,
  `post_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `post_modified_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `post_content_filtered` longtext NOT NULL,
  `post_parent` bigint(20) unsigned NOT NULL DEFAULT '0',
  `guid` varchar(255) NOT NULL DEFAULT '',
  `menu_order` int(11) NOT NULL DEFAULT '0',
  `post_type` varchar(20) NOT NULL DEFAULT 'post',
  `post_mime_type` varchar(100) NOT NULL DEFAULT '',
  `comment_count` bigint(20) NOT NULL DEFAULT '0',
  PRIMARY KEY (`ID`),
  KEY `post_name` (`post_name`),
  KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
  KEY `post_parent` (`post_parent`),
  KEY `post_author` (`post_author`)
) ENGINE=MyISAM AUTO_INCREMENT=1331 DEFAULT CHARSET=utf8;
1 row in set (0.00 sec)

一見、utf8でよさそうに見えますが、MySQLのutf8は4byte超の文字を扱えないようです。(3byteまでだとか)
ですので、絵文字(Unicode6.0)が扱えないのです。(これだと絵文字に限らず漢字とかも登録できない文字があります)

解決方法

MySQL 5.5.3 以降で、CHARSETutf8mb4を指定してやれば4byte(UTF-8)の文字も扱えるようになります。
WordPress 公式サイトに書かれてある動作環境では、「MySQLのバージョン 5.0以上」としか書かれていないので、お使いの環境ではutf8mb4を指定できないかもしれないのでご注意ください。

注意: 以下の設定は、直接データベースに変更を加えます。復旧できるようにバックアップ等を行ってください。変更によって生じた如何なる損害に関しても、著者は責任を負いかねます。

WordPressの文字コード設定を変更する

wp-config.phpの変更を行います。
DB_CHARSET, DB_COLLATEのそれぞれを以下のように変更します。


/** データベースのテーブルを作成する際のデータベースのキャラクターセット */
define('DB_CHARSET', 'utf8mb4');

/** データベースの照合順序 (ほとんどの場合変更する必要はありません) */
define('DB_COLLATE', 'utf8mb4_general_ci');

データベースの文字コードを変更する

alter database wp character set utf8mb4;

データベース名など各自の環境に合わせてください。

mysql> alter database wp character set utf8mb4;
Query OK, 1 row affected (0.02 sec)

mysql> SHOW CREATE DATABASE wp;
+----------+----------------------------------------------------------------+
| Database | Create Database                                                |
+----------+----------------------------------------------------------------+
| wp       | CREATE DATABASE `wp` /*!40100 DEFAULT CHARACTER SET utf8mb4 */ |
+----------+----------------------------------------------------------------+
1 row in set (0.00 sec)

テーブルの文字コードを変更する

alter table wp_posts convert to character set utf8mb4;

ここではwp_postsを例にしていますが、別のテーブルで使用する場合は同じ操作をおこなってください。

mysql> alter table wp_posts convert to character set utf8mb4;
Query OK, 985 rows affected (0.20 sec)
Records: 985  Duplicates: 0  Warnings: 0

mysql> show create table wp_posts \G
*************************** 1. row ***************************
       Table: wp_posts
Create Table: CREATE TABLE `wp_posts` (
  `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `post_author` bigint(20) unsigned NOT NULL DEFAULT '0',
  `post_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `post_date_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `post_content` longtext NOT NULL,
  `post_title` mediumtext NOT NULL,
  `post_excerpt` mediumtext NOT NULL,
  `post_status` varchar(20) NOT NULL DEFAULT 'publish',
  `comment_status` varchar(20) NOT NULL DEFAULT 'open',
  `ping_status` varchar(20) NOT NULL DEFAULT 'open',
  `post_password` varchar(20) NOT NULL DEFAULT '',
  `post_name` varchar(200) NOT NULL DEFAULT '',
  `to_ping` mediumtext NOT NULL,
  `pinged` mediumtext NOT NULL,
  `post_modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `post_modified_gmt` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `post_content_filtered` longtext NOT NULL,
  `post_parent` bigint(20) unsigned NOT NULL DEFAULT '0',
  `guid` varchar(255) NOT NULL DEFAULT '',
  `menu_order` int(11) NOT NULL DEFAULT '0',
  `post_type` varchar(20) NOT NULL DEFAULT 'post',
  `post_mime_type` varchar(100) NOT NULL DEFAULT '',
  `comment_count` bigint(20) NOT NULL DEFAULT '0',
  PRIMARY KEY (`ID`),
  KEY `post_name` (`post_name`),
  KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
  KEY `post_parent` (`post_parent`),
  KEY `post_author` (`post_author`)
) ENGINE=MyISAM AUTO_INCREMENT=1331 DEFAULT CHARSET=utf8mb4;
1 row in set (0.02 sec)

おわり

以上の設定変更で絵文字(Unicode6.0)が使えるようになります。
XAMPP for Windows で確認したので Linux環境とかではまた動作が異なることも考えられますが、おそらく大丈夫かと思います。参考までに。

テストしていて気付いたのですが、無理に使わずに文字参照を使えばこれらの設定変更不要でした…。
文末ですが、リスキーだと感じた方は🙉のような形で埋め込むことをお勧めします。🙉