在 WordPress 5 下用 SQL 获取所有分类

关键字

WordPress, WordPress 5, Category, Taxonomy, SQL

问题

通过阅读 WordPress 5 源码,大概可定位与获取分类有关的类在以下文件中,但要读懂并不容易。

wp-includes\class-wp-term-query.php

但如果不想使用 PHP 语言,使用其他语言时,如何通过较通用的 SQL 方式读取所有分类。

分析

要写出这个 SQL 需要了解表结构,但 WordPress 没有在 MySQL 数据库中使用外键约束,当然,这也是数据库最普遍的用法。

在 WordPress 的数据库中,有两张表与分类有关,wp_term_taxonomy 和 wp_terms。

wp_term_taxonomy 是分类法表,分类法 taxonomy 其实就是支持多种分类方法,并且支持多级分类,用一个 parent 字段来定义。

WordPress 把标签也作为一种分类法。wp_term_taxonomy 中也存储了标签,为和文章分类区分,使用一个 taxonomy 字段,当 taxonomy 为 category 时,数据是文章分类;当 taxonomy 是 post_tag 时,数据是文章标签。

也许是历史原因,WordPress 将不同分类法的定义放在一个表中,把分类的名称定义在 wp_terms 表中。

SQL 获取 WordPress 5 分类

SELECT t2.term_id, t4.name, t1.term_id, t3.name AS parent_name, t1.count
FROM wp_term_taxonomy AS t1
  LEFT JOIN wp_term_taxonomy AS t2 ON t1.parent = t2.term_id
  LEFT JOIN wp_terms AS t3 ON t3.term_id = t1.term_id
  LEFT JOIN wp_terms AS t4 ON t4.term_id = t2.term_id
WHERE t1.taxonomy='category'
ORDER BY t2.term_id, t1.term_id

这个获取的结果已经过了排序,我们可以通过一个循环将数据绑定在一棵树上展示。

关于 WP 的评论

坦白来说,WordPress 这个项目很成功,但设计却没有保持 KISS 原则,代码比较不规整,还有历史原因导致某些设计需要兼容旧设计,而不够优雅,代码质量和可维护性也可想而知。

然后,我想说的是,这就是真实世界的代码,因为代码总是描述真实世界,那种优雅的假设只存在于设计和假设中,当遇到现实的细节时,复杂度就会叠加。项目在各种限制下,还需要继续向前推进,而不能停下来完整的重构。

往往也需要做出一些 BC 的牺牲,这点上,可以去读读 Windows 程序的源代码,就有更有感想了。

WordPress官方提到的分类法在 4.2 中为了保持向后兼容

其实可以用一句话说清楚:wp_term_taxonomy 的主键已经没大的作用,通常我们应该使用 term_id,parent 用来关联的也是 term_id,不是 term_taxonomy_id。

以下是官方举例的翻译

技术细节和向后兼容

wp_term_taxonomy 表中的每一行代表这个分类和它的固定链接路径,如标签 mint 和分类 herb。历史上,具有相同固定链接路径的不同分类法的词汇在 wp_terms 表中用同一行表示。那样的话,wp_terms 表中 mint 行可能和 herb 一样,会对应到 government_building 词汇。

启动 4.2 版本后,当你更新一个共享的词汇,wp_update_term( $mint_id, 'government_building' ) WordPress 会探测到,是否一个词汇属于多个分类法,如果是的话,将会在 wp_terms 表中创建新行以更新所有的新词。term_taxonomy_id 将会保留一致,但 term_id 会变化。这就是一个共享词汇被拆分开的例子。

大多数情况下,词汇拆分不会被注意到。然后,会有某些插件和主题保存了词汇 id作为静态数据,在这些例子中,词汇 id 变化的话,会导致更重问题。

谁会受影响?

简单地说,任何在数据库中保存了词汇主键的就会受影响。

发表评论

电子邮件地址不会被公开。 必填项已用*标注