WordPress源码深度解析之:`WordPress`的`Taxonomy Meta`:如何为分类法添加元数据。

各位亲爱的开发者们,晚上好!我是你们的老朋友,今天咱们来聊聊WordPress分类法(Taxonomy)的元数据(Meta)。

分类法,简单来说,就是给你的文章、商品等内容打标签,让它们更有条理。比如文章分类、商品类别等等。而元数据,就像是这些标签的附加信息,让你的分类法更加强大。

一、 为什么要给分类法添加元数据?

想象一下,你开了一家在线书店,书籍按照“小说”、“历史”、“科幻”等分类。如果只是这样,未免太单薄了。

  • 小说分类:你想添加一个“推荐指数”的元数据,让用户知道哪些小说更受欢迎。
  • 历史分类:你想添加一个“所属朝代”的元数据,方便用户按朝代查找历史书籍。
  • 科幻分类:你想添加一个“硬科幻/软科幻”的元数据,满足不同科幻爱好者的需求。

这就是分类法元数据的意义:扩展分类法的功能,让你的网站更灵活、更个性化。

二、 WordPress内置的分类法元数据

WordPress 4.4版本之后,内置了分类法元数据的功能。这意味着你无需安装额外的插件,就可以轻松为分类法添加元数据。

WordPress为此新增了几个函数:

  • get_term_meta( $term_id, $key, $single = false ): 获取分类法的元数据。
  • update_term_meta( $term_id, $key, $value, $prev_value = '' ): 更新分类法的元数据。
  • add_term_meta( $term_id, $key, $value, $unique = false ): 添加分类法的元数据。
  • delete_term_meta( $term_id, $key, $value = '', $delete_all = false ): 删除分类法的元数据。

这些函数和文章的元数据函数(get_post_metaupdate_post_meta等)非常相似,用起来也很容易上手。

三、 动手实践:添加一个“分类描述”的元数据

咱们以最常见的“category”(文章分类)为例,添加一个“分类描述”的元数据。这个元数据可以在分类编辑页面显示一个文本框,让管理员填写分类的详细描述。

1. 添加后台编辑字段

我们需要在分类编辑页面添加一个文本框,让管理员填写“分类描述”。 这需要用到edit_category_form_fields钩子。

add_action( 'edit_category_form_fields', 'add_category_description_field' );

function add_category_description_field( $term ) {
    // 获取当前的分类描述
    $term_id = $term->term_id;
    $term_description = get_term_meta( $term_id, 'category_description', true );

    ?>
    <tr class="form-field">
        <th scope="row" valign="top"><label for="category_description"><?php _e( '分类描述', 'your-textdomain' ); ?></label></th>
        <td>
            <textarea name="category_description" id="category_description" rows="5" cols="50" class="large-text"><?php echo esc_textarea( $term_description ); ?></textarea>
            <br />
            <span class="description"><?php _e( '这个分类的详细描述。', 'your-textdomain' ); ?></span>
        </td>
    </tr>
    <?php
}

这段代码做了什么?

  • add_action( 'edit_category_form_fields', 'add_category_description_field' );: 将add_category_description_field函数挂载到edit_category_form_fields钩子上,在分类编辑页面显示自定义字段。
  • $term_id = $term->term_id;: 获取当前分类的ID。
  • $term_description = get_term_meta( $term_id, 'category_description', true );: 获取分类的“category_description”元数据。true表示只获取单个值。
  • <textarea ...>: 创建一个文本框,用于输入分类描述。
  • esc_textarea( $term_description ): 对文本框中的内容进行转义,防止XSS攻击。
  • __( '分类描述', 'your-textdomain' )__( '这个分类的详细描述。', 'your-textdomain' ): 使用WordPress的国际化函数,方便网站进行多语言翻译。

2. 保存分类描述

接下来,我们需要保存管理员填写的“分类描述”。 这需要用到edited_category钩子。

add_action( 'edited_category', 'save_category_description' );

function save_category_description( $term_id ) {
    if ( isset( $_POST['category_description'] ) ) {
        $term_description = sanitize_textarea_field( $_POST['category_description'] );
        update_term_meta( $term_id, 'category_description', $term_description );
    }
}

这段代码做了什么?

  • add_action( 'edited_category', 'save_category_description' );: 将save_category_description函数挂载到edited_category钩子上,在分类保存时执行。
  • if ( isset( $_POST['category_description'] ) ): 检查category_description字段是否被提交。
  • $term_description = sanitize_textarea_field( $_POST['category_description'] );: 对提交的分类描述进行安全过滤,防止XSS攻击。
  • update_term_meta( $term_id, 'category_description', $term_description );: 更新分类的“category_description”元数据。

3. 在前端显示分类描述

现在,我们已经成功添加并保存了分类描述。接下来,我们需要在前端显示这个描述。

$term = get_queried_object();
if ( $term && ! is_wp_error( $term ) ) {
    $term_id = $term->term_id;
    $term_description = get_term_meta( $term_id, 'category_description', true );

    if ( ! empty( $term_description ) ) {
        echo '<div class="category-description">';
        echo wp_kses_post( $term_description );
        echo '</div>';
    }
}

这段代码做了什么?

  • get_queried_object();: 获取当前查询的对象,如果是分类页面,则返回分类对象。
  • $term_id = $term->term_id;: 获取分类的ID。
  • $term_description = get_term_meta( $term_id, 'category_description', true );: 获取分类的“category_description”元数据。
  • if ( ! empty( $term_description ) ): 检查分类描述是否为空。
  • wp_kses_post( $term_description );: 对分类描述进行安全过滤,允许HTML标签,但会移除恶意代码。

将这段代码添加到你的分类模板(通常是category.php或者archive.php)中,就可以在分类页面显示分类描述了。

四、 进阶:自定义字段类型

上面的例子只是添加了一个简单的文本框。如果你需要更复杂的字段类型,比如下拉菜单、单选框、复选框等等,就需要自己动手实现。

1. 使用edit_category_form_fields钩子添加自定义字段

和上面的例子类似,你可以使用edit_category_form_fields钩子来添加自定义字段。只需要根据你的需求,修改HTML代码即可。

例如,添加一个“分类颜色”的单选框:

add_action( 'edit_category_form_fields', 'add_category_color_field' );

function add_category_color_field( $term ) {
    $term_id = $term->term_id;
    $term_color = get_term_meta( $term_id, 'category_color', true );

    $colors = array(
        'red'   => '红色',
        'green' => '绿色',
        'blue'  => '蓝色',
    );

    ?>
    <tr class="form-field">
        <th scope="row" valign="top"><label for="category_color"><?php _e( '分类颜色', 'your-textdomain' ); ?></label></th>
        <td>
            <?php foreach ( $colors as $color_value => $color_label ) : ?>
                <label>
                    <input type="radio" name="category_color" value="<?php echo esc_attr( $color_value ); ?>" <?php checked( $term_color, $color_value ); ?> />
                    <?php echo esc_html( $color_label ); ?>
                </label>
                <br />
            <?php endforeach; ?>
            <span class="description"><?php _e( '选择分类的颜色。', 'your-textdomain' ); ?></span>
        </td>
    </tr>
    <?php
}

2. 使用edited_category钩子保存自定义字段

同样,你需要使用edited_category钩子来保存自定义字段。

add_action( 'edited_category', 'save_category_color' );

function save_category_color( $term_id ) {
    if ( isset( $_POST['category_color'] ) ) {
        $term_color = sanitize_text_field( $_POST['category_color'] );
        update_term_meta( $term_id, 'category_color', $term_color );
    }
}

3. 在前端显示自定义字段

最后,在前端显示自定义字段。

$term = get_queried_object();
if ( $term && ! is_wp_error( $term ) ) {
    $term_id = $term->term_id;
    $term_color = get_term_meta( $term_id, 'category_color', true );

    if ( ! empty( $term_color ) ) {
        echo '<div class="category-color ' . esc_attr( $term_color ) . '">';
        echo '</div>';
    }
}

五、 高级技巧:使用插件增强功能

虽然WordPress内置了分类法元数据功能,但如果你需要更强大的功能,比如:

  • 可视化编辑器: 使用可视化编辑器编辑分类描述。
  • 图片上传: 为分类添加图片。
  • 自定义字段组: 将多个自定义字段组合在一起。

可以考虑使用一些流行的插件,比如:

  • Advanced Custom Fields (ACF): 功能强大的自定义字段插件,支持各种字段类型和高级功能。
  • Meta Box: 另一个流行的自定义字段插件,提供了类似的功能。

这些插件可以让你更轻松地管理分类法元数据,提高开发效率。

六、 代码示例:一个完整的例子

下面是一个完整的例子,演示了如何为“category”分类添加一个“分类封面图片”的元数据。

1. 添加后台编辑字段

add_action( 'edit_category_form_fields', 'add_category_image_field' );

function add_category_image_field( $term ) {
    $term_id = $term->term_id;
    $term_image_id = get_term_meta( $term_id, 'category_image', true );
    $term_image_url = wp_get_attachment_image_url( $term_image_id, 'thumbnail' );

    ?>
    <tr class="form-field">
        <th scope="row" valign="top"><label for="category_image"><?php _e( '分类封面图片', 'your-textdomain' ); ?></label></th>
        <td>
            <img id="category_image_preview" src="<?php echo esc_url( $term_image_url ); ?>" style="max-width: 150px; max-height: 150px; display: <?php echo $term_image_url ? 'block' : 'none'; ?>;" />
            <input type="hidden" id="category_image" name="category_image" value="<?php echo esc_attr( $term_image_id ); ?>" />
            <button type="button" class="button" id="upload_category_image_button"><?php _e( '上传图片', 'your-textdomain' ); ?></button>
            <button type="button" class="button" id="remove_category_image_button" style="display: <?php echo $term_image_id ? 'inline-block' : 'none'; ?>;"><?php _e( '移除图片', 'your-textdomain' ); ?></button>
            <br />
            <span class="description"><?php _e( '选择分类的封面图片。', 'your-textdomain' ); ?></span>
        </td>
    </tr>
    <script>
        jQuery(document).ready(function($) {
            var mediaUploader;

            $('#upload_category_image_button').click(function(e) {
                e.preventDefault();

                if (mediaUploader) {
                    mediaUploader.open();
                    return;
                }

                mediaUploader = wp.media.frames.file_frame = wp.media({
                    title: '选择图片',
                    button: {
                        text: '选择图片'
                    },
                    multiple: false  //  Set to true to allow multiple files to be selected
                });

                mediaUploader.on('select', function() {
                    var attachment = mediaUploader.state().get('selection').first().toJSON();
                    $('#category_image').val(attachment.id);
                    $('#category_image_preview').attr('src', attachment.url).show();
                    $('#remove_category_image_button').show();
                });

                mediaUploader.open();
            });

            $('#remove_category_image_button').click(function(e) {
                e.preventDefault();
                $('#category_image').val('');
                $('#category_image_preview').attr('src', '').hide();
                $(this).hide();
            });
        });
    </script>
    <?php
}

2. 保存分类封面图片

add_action( 'edited_category', 'save_category_image' );

function save_category_image( $term_id ) {
    if ( isset( $_POST['category_image'] ) ) {
        $term_image_id = absint( $_POST['category_image'] );
        update_term_meta( $term_id, 'category_image', $term_image_id );
    }
}

3. 在前端显示分类封面图片

$term = get_queried_object();
if ( $term && ! is_wp_error( $term ) ) {
    $term_id = $term->term_id;
    $term_image_id = get_term_meta( $term_id, 'category_image', true );
    $term_image_url = wp_get_attachment_image_url( $term_image_id, 'medium' ); // Use 'medium' size

    if ( ! empty( $term_image_url ) ) {
        echo '<div class="category-image">';
        echo '<img src="' . esc_url( $term_image_url ) . '" alt="' . esc_attr( $term->name ) . '" />';
        echo '</div>';
    }
}

4. 确保Media Uploader脚本加载

这个例子使用了WordPress的Media Uploader,你需要确保在后台正确加载了相关的JavaScript文件。 可以在你的插件或主题的functions.php文件中添加以下代码:

add_action( 'admin_enqueue_scripts', 'load_media_files' );

function load_media_files( $hook ) {
    if ( 'edit-tags.php' != $hook ) {
        // Only loads on edit-tags.php page
        return;
    }
    wp_enqueue_media();
}

表格总结:函数速查

函数名 作用 参数 返回值
get_term_meta() 获取分类法元数据 $term_id (int), $key (string), $single (bool, 可选) 成功:元数据值,失败:空字符串
update_term_meta() 更新分类法元数据 $term_id (int), $key (string), $value (mixed), $prev_value (mixed, 可选) 成功:true,失败:false
add_term_meta() 添加分类法元数据 $term_id (int), $key (string), $value (mixed), $unique (bool, 可选) 成功:元数据ID,失败:false
delete_term_meta() 删除分类法元数据 $term_id (int), $key (string), $value (mixed, 可选), $delete_all (bool, 可选) 成功:true,失败:false
edit_category_form_fields 编辑分类表单的钩子,用于添加自定义字段 $term (object) 当前分类对象
edited_category 编辑分类的钩子,用于保存自定义字段 $term_id (int) 当前分类ID
wp_enqueue_media() 加载媒体上传所需的文件(js,css)

七、 总结

今天我们一起学习了WordPress分类法元数据的用法。希望大家能够灵活运用这些知识,为自己的网站添加更多个性化的功能。 记住,安全第一,一定要对用户输入进行安全过滤! 如果有任何问题,欢迎随时提问。 谢谢大家!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注