默认情况下,在 typecho 创建有 emoji 表情符的文章时,会提示 Database Query Error 错误。

首先,使用以下两条命令检查一下表和字段的字符集用的是什么。

SHOW CREATE TABLE typecho_contents;
SHOW FULL COLUMNS FROM typecho_contents;

运行结果是:

mysql> SHOW CREATE TABLE typecho_contents;

 typecho_contents | CREATE TABLE `typecho_contents` (
  `cid` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(200) DEFAULT NULL,
  `slug` varchar(200) DEFAULT NULL,
  `created` int(10) unsigned DEFAULT '0',
  `modified` int(10) unsigned DEFAULT '0',
  `text` longtext,
  `order` int(10) unsigned DEFAULT '0',
  `authorId` int(10) unsigned DEFAULT '0',
  `template` varchar(32) DEFAULT NULL,
  `type` varchar(16) DEFAULT 'post',
  `status` varchar(16) DEFAULT 'publish',
  `password` varchar(32) DEFAULT NULL,
  `commentsNum` int(10) unsigned DEFAULT '0',
  `allowComment` char(1) DEFAULT '0',
  `allowPing` char(1) DEFAULT '0',
  `allowFeed` char(1) DEFAULT '0',
  `parent` int(10) unsigned DEFAULT '0',
  PRIMARY KEY (`cid`),
  UNIQUE KEY `slug` (`slug`),
  KEY `created` (`created`)
) ENGINE=MyISAM AUTO_INCREMENT=278 DEFAULT CHARSET=utf8 |
1 row in set (0.00 sec)


mysql> SHOW FULL COLUMNS FROM typecho_contents;
+--------------+------------------+-----------------+
| Field        | Type             | Collation       |
+--------------+------------------+-----------------+
| cid          | int(10) unsigned | NULL            |
| title        | varchar(200)     | utf8_general_ci |
| slug         | varchar(200)     | utf8_general_ci |
| created      | int(10) unsigned | NULL            |
| modified     | int(10) unsigned | NULL            |
| text         | longtext         | utf8_general_ci |
| order        | int(10) unsigned | NULL            |
| authorId     | int(10) unsigned | NULL            |
| template     | varchar(32)      | utf8_general_ci |
| type         | varchar(16)      | utf8_general_ci |
| status       | varchar(16)      | utf8_general_ci |
| password     | varchar(32)      | utf8_general_ci |
| commentsNum  | int(10) unsigned | NULL            |
| allowComment | char(1)          | utf8_general_ci |
| allowPing    | char(1)          | utf8_general_ci |
| allowFeed    | char(1)          | utf8_general_ci |
| parent       | int(10) unsigned | NULL            |
+--------------+------------------+-----------------+
17 rows in set (0.00 sec)

可以看到,typecho 实际是给表设置了 utf8 字符集。我们知道在 MySQL 中,utf8 实际上是阉割版,真正的 UTF-8 应该用 utf8mb4,使用以下命令修改表的默认字符集:

ALTER TABLE typecho_contents DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

我的表里已经有了一些数据,执行效果如下:

mysql> ALTER TABLE typecho_contents DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Query OK, 253 rows affected (0.01 sec)
Records: 253  Duplicates: 0  Warnings: 0

继续查看表结构,发现修改后表的默认字符集确实改变了,但字段的并没有。下面我们来修改一下存储文章内容字段的字符集。

ALTER TABLE typecho_contents CHANGE `text` `text` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE typecho_contents CHANGE `title` `title` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE typecho_contents CHANGE `slug` `slug` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

注意,我们这里只修改了文章的内容字段的字符集,其他表没有修改,如果需要评论也支持的话,修改相应的表字段就行了。

此时再保存文章,发现还是报错。问题就在于 typecho 的配置代码没改。

在 typecho 的项目根目录下,编辑 config.inc.php 文件,在配置数据库连接那一段:

/** 定义数据库参数 */
$db = new Typecho_Db('Pdo_Mysql', 'typecho_');
$db->addServer(array (
  'host' => 'localhost',
  'user' => 'root',
  'password' => '123456',
  'charset' => 'utf8mb4',
  'port' => '3306',
  'database' => 'typecho',
), Typecho_Db::READ | Typecho_Db::WRITE);
Typecho_Db::set($db);

charset 改为 utf8mb4 即可。

再次保存,问题解决。


总结

最简单的方法两步即可解决问题。

  1. 修改文章内容字段的字符编码:

    ALTER TABLE typecho_contents CHANGE `text` `text` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  2. 修改 typecho 配置文件 config.inc.php,将 MySQL 连接的 charset 配置参数改为 utf8mb4

标签: typecho

添加新评论