WordPress插件开发教程手册 — 自定义分类方法
分类法是类别和分组的另外一种说法,分类法可以是分级的和扁平的。WordPress 可以让插件开发者注册自定义分类法,分类法存储在 term_taxonomy 数据表中。分类法中有一些分类法项目,这些项目存储在 wp_terms 数据表中。例如,名为 “艺术” 的分类方法有多个分类项目,如 “现在艺术” 和 “18 世纪艺术”。
本章我们来学习怎么注册自定义分类方法,如何从数据库中获取自定义分类方法内容,以及如何显示给用户。
使用自定义分类法
自定义分类方法
随着分类法系统的推出,WordPress 默认的分类方法 “分类目录” 和 “标签” 很多时候已经不能满足我们的需求,这个时候,我们可以创建自定义分类方法。自定义分类方法通常和自定义文章类型一起使用,为我们自定义的某种内容按照我们自定义的条件分类。
为什么使用自定义分类方法
有些开发者可能会问,为什么要使用分类方法,使用分类方法可以为我们带来什么好处?什么时候使用分类方法来组织内容?下面我们就用一个例子来说明一下使用分类方法的好处。假设有一个客户是厨师,他需要我们帮他使用 WordPress 创建一个网站,用来展示他的食谱。
为了避免 “食谱” 这种类型的内容和其他内容混在一起,引起管理上的混乱,我们需要创建一个自定义文章类型 “食谱” 来存储这个厨师的食谱内容。食谱当然会有分类,我们需要创建一个名为 “课程” 的分类方法来把 “开胃菜” 和 “甜点” 这两种不同的食谱分开,然后创建一个 “原料” 的分类方法来根据原料的不同把食谱分为 “鸡肉” 换 “巧克力”等。
当然,我们也可以使用默认的“分类目录” 和 “标签” 来组织食谱的内容,这种情况下,我们需要创建一个名为 “课程” 的分类,然后创建 “开胃菜” 和 “甜点” 子分类,以及 “原料” 分类和他们的子分类。
使用自定义分类方法的主要优点在于我们可以使用独立于“分类目录” 和 “标签”的分类系统来区分我们的食谱,自定义分类方法在 WordPress 后台有自己独立的菜单,也更方便我们管理。此外,创建自定义分类方法还允许我们创建自定义界面和数据出入流程,来降低用户的学习和使用成本。如果在插件中创建了自定义分类方法,我们还可以在不同的 WordPress 网站上重复使用。
示例:课程分类方法
下面的示例将展示如何创建一个自定义分类方法“课程”,并把这个自定义分类方法添加到默认的“文章”文章类型中。在尝试创建插件之前,请确保阅读了插件开发基础知识章节。
第一步:开始之前
打开:文章>写文章 页面,我们可以看到默认有分类目录和标签这两种分类方法。
第二步:创建一个新插件
使用 init Action 钩子为内容类型 “文章” 注册一个自定义分类方法 “课程”。
/*
* Plugin Name: Course Taxonomy
* Description: A short example showing how to add a taxonomy called Course.
* Version: 1.0
* Author: developer.wordpress.org
* Author URI: https://codex.wordpress.org/User:Aternus
*/
function wporg_register_taxonomy_course() {
$labels = [
'name' => _x( 'Courses', 'taxonomy general name' ),
'singular_name' => _x( 'Course', 'taxonomy singular name' ),
'search_items' => __( 'Search Courses' ),
'all_items' => __( 'All Courses' ),
'parent_item' => __( 'Parent Course' ),
'parent_item_colon' => __( 'Parent Course:' ),
'edit_item' => __( 'Edit Course' ),
'update_item' => __( 'Update Course' ),
'add_new_item' => __( 'Add New Course' ),
'new_item_name' => __( 'New Course Name' ),
'menu_name' => __( 'Course' ),
];
$args = [
'hierarchical' => true, // make it hierarchical (like categories)
'labels' => $labels,
'show_ui' => true,
'show_admin_column' => true,
'query_var' => true,
'rewrite' => [ 'slug' => 'course' ],
];
register_taxonomy( 'course', [ 'post' ], $args );
}
add_action( 'init', 'wporg_register_taxonomy_course' );
第三步:查看结果
激活我们刚才创建的插件,然后打开文章>写文章 页面,如果一切顺利,我们将看到一个名称为 “课程” 的分类方法。
代码解读
下面我们来逐一了解用于实现上面功能的函数和参数。
函数 wporg_register_taxonomy_course 注册自定义文章类型所需要的所有步骤。
$label 数据中定义了自定义分类方法的标签,也就是我们在后台看到的分类方法的名称、操作等各种信息。
$args 参数包含创建自定义分类方法时使用的配置选项,用来指示 WordPress 怎么设置自定义分类方法。
register_taxonomy() 函数使用 $args 数组为“文章” 这个内容类型配置了课程分类方法。
add_action() 函数把创建分类方法的操作绑定到了 init Action 钩子上。
总结
通过我们创建 “课程” 分类方法的示例代码, WordPress 将自动为 “课程” 分类方法创建存档页面及其子页面。
自定义分类方法存档页面的形式为 (/course/%%term-slug%%/
),其中 /course/
为自定义分类方法的标识符,%%term-slug%%
为自定义分类方法中分类项目别名。
使用自定义分类法
WordPress 中有很多函数可以操作自定义分类法和自定义分类法中的分类项目。如:
the_terms
:接受分类法参数,在列表中显示分类法项目。wp_tag_cloud
:接受分类法参数,以标签云的形式显示分类法项目。is_taxonomy
:判断是否为指定的分类方法。
拆分分类法项目(WordPress 4.2+)
WordPress 4.2 以前
在 WordPress 4.2 以前,不同分类方法中使用的相同分类法项目会共享一个分类法项目 ID,例如,具有相同别名 “news” 的分类目录和标签共享一个 ID,其实他们是一个分类法项目。
WordPress 4.2 以后
从 WordPress 4.2 开发,这些共享的分类法项目被更新后,他们会被拆分为单独的项目,每个项目会被分配一个新的 ID。
这意味着什么
绝大多数情况下,这个更新是无缝和平滑的,但是,一些插件和主题会把一些分类法 ID 存储到 options, post_meta, user_meta 或其他数据中,这些情况下,主题或插件可能会受到影响。
处理分类法项目分拆
WordPress 4.2 提供了两个不通的工具来帮助插件和主题开发者进行转换。
split_shared_term 钩子
如果共享的分类法项目被分配了新的 ID,会自动触发挂载到 split_share_term 钩子上的操作。以下是主题和插件开发者使用此钩子确保存储的分类法项目 ID 被更新的示例。
存储在选项中
假如我们的插件存储了一个名为 feartured_tags 的选项,其中包含了一个标签 ID 数组 ( [4,6,10] ),该选项为主页精选文章模块的查询参数。在这个例子中,我们将挂载一个函数到 split_shared_term Action 钩子上,该函数会检查标签 ID 是否在数组中,如果有需要,会更新这个数组。
/**
* Update featured_tags option when a shared term gets split.
*
* @param int $term_id ID of the formerly shared term.
* @param int $new_term_id ID of the new term created for the $term_taxonomy_id.
* @param int $term_taxonomy_id ID for the term_taxonomy row affected by the split.
* @param string $taxonomy Taxonomy for the split term.
*/
function wporg_featured_tags_split( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
// we only care about tags, so we'll first verify that the taxonomy is post_tag.
if ( $taxonomy === 'post_tag' ) {
// get the currently featured tags.
$featured_tags = get_option( 'featured_tags' );
// if the updated term is in the array, note the array key.
$found_term = array_search( $term_id, $featured_tags );
if ( $found_term !== false ) {
// the updated term is a featured tag! replace it in the array, save the new array.
$featured_tags[ $found_term ] = $new_term_id;
update_option( 'featured_tags', $featured_tags );
}
}
}
add_action( 'split_shared_term', 'wporg_featured_tags_split', 10, 4 );
存储在 post_meta 中
假如,插件为页面保存了一个标签 ID,通过这个标签 ID,我们可以在文章页面中显示相关文章。这种情况下,我们先通过 get_psots() 函数来获取 meta_key 和 meta_value 匹配的页面,然后更新 meta_value 为分割后的 ID。
/**
* Update related posts term ID for pages
*
* @param int $term_id ID of the formerly shared term.
* @param int $new_term_id ID of the new term created for the $term_taxonomy_id.
* @param int $term_taxonomy_id ID for the term_taxonomy row affected by the split.
* @param string $taxonomy Taxonomy for the split term.
*/
function wporg_page_related_posts_split( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
// find all the pages where meta_value matches the old term ID.
$page_ids = get_posts( [
'post_type' => 'page',
'fields' => 'ids',
'meta_key' => 'meta_key',
'meta_value' => $term_id,
] );
// if such pages exist, update the term ID for each page.
if ( $page_ids ) {
foreach ( $page_ids as $id ) {
update_post_meta( $id, 'meta_key', $new_term_id, $term_id );
}
}
}
add_action( 'split_shared_term', 'wporg_page_related_posts_split', 10, 4 );
wp_get_split_term 函数
WordPress 会保存拆分后的分类法项目信息,并提供了 wp_get_split_term() 函数 来帮助开发人员获取此信息。
考虑一下上面的情况,我们的插件存储了一个名为 feartured_tags,值为分类法项目 ID 的数组选项,我们可能需要创建一个函数来检查这些 ID(可以在插件更新的时候)中是否包含已被拆分的 ID,如果包含,我们需要更新被拆分后分类法项目 ID 到这个数组中。
function wporg_featured_tags_check_split() {
$featured_tag_ids = get_option( 'featured_tags', [] );
// check to see whether any IDs correspond to post_tag terms that have been split.
foreach ( $featured_tag_ids as $index => $featured_tag_id ) {
$new_term_id = wp_get_split_term( $featured_tag_id, 'post_tag' );
if ( $new_term_id ) {
$featured_tag_ids[ $index ] = $new_term_id;
}
}
// save
update_option( 'featured_tags', $featured_tag_ids );
}
注意, wp_get_split_term() 接受两个参数,$old_term_id
和 $taxonomy
,并返回一个整数。
如果我们需要获取所有分类法中与旧分类法 ID 相关的拆分分类法项目列表,我们可以使用 wp_get_split_terms() 函数 。
1 thoughts on “WordPress插件开发教程手册 — 自定义分类方法”
创建后,写文章的页面没有出现