描述

昨天刚装完Sakura主题(版本3.4.0),今天下午配置评论区的时候发现,发送新评论时会报WordPress数据库错误。

报错截图

当时正好请了个朋友来尝试评论一下,发现会返回同样的错误,但是评论仍然能正常显示。

分析

[22-Oct-2022 11:45:27 UTC] 
WordPress数据库查询ALTER TABLE wp_comments ADD comment_markdown text时发生Duplicate column name 'comment_markdown'错误,这是由do_action('wp_ajax_nopriv_ajax_comment'), WP_Hook->do_action, WP_Hook->apply_filters, siren_ajax_comment_callback, wp_handle_comment_submission, wp_new_comment, apply_filters('preprocess_comment'), WP_Hook->apply_filters, markdown_parser查询的

从日志可以看出,报错的原因是在列已存在的情况下重复添加comment_markdown这一列导致的。虽然报错,但并不会对数据库产生什么影响。

评论的存储

在Sakura中,评论本身的内容部分是在[你的WordPress数据库].wp_comments中单独新建了comment_markdown一列来存储Markdown文本的,而WordPress自带的comment_content用来存储Markdown内容对应的HTML内容,相当于一份评论以两种形式存了两遍。

HTML格式
Markdown格式

代码

简单看了一下Sakura的源码,在functions.php里的markdown_parser函数中有这样一段:

//Add column if not present.
if (!isset($myCustomer->comment_markdown)) {
    $wpdb->query("ALTER TABLE wp_comments ADD comment_markdown text");
}

大体意思就是利用判断myCustomer类中的comment_markdown变量是否为集合变量来决comment_markdown这一列是否存在,不存在则用ALTER命令在数据库中新增这一列。

其中的myCustomer是这样定义的:

$myCustomer = $wpdb->get_row("SELECT comment_markdown FROM wp_comments");

wpdbWordPress提供的一个用于对数据库进行一系列操作的函数类。get_row是其中的一个用于返回query结果的成员函数。返回类型为数组、对象、null或者void。

官方说明文档

所以很明显,用判断是否为集合的方法判断是否包含comment_markdown列的方法并不可行,因为get_row函数不会返回集合类,所以结果永远为false,所以才会总是误认定数据库中没有comment_markdown这一列而导致每次添加评论都会尝试在表中新建这一列。

解决

重新定义myCustomercomment_markdown这一列的查询返回结果,因此如果myCustomer为空就代表列不存在,此时再向表中新建列即可。

// debug
// $myCustomer = $wpdb->get_row("SELECT * FROM wp_comments");
$myCustomer = $wpdb->get_row("SELECT comment_markdown FROM wp_comments");

//Add column if not present.
// if (!isset($myCustomer->comment_markdown)) {
if (!$myCustomer) {
    $wpdb->query("ALTER TABLE wp_comments ADD comment_markdown text");
}
Beautiful things don't ask for attention.
Last updated on 2023-12-25