Back to Blog

meta_boxの使い方

WordPress

2024/06/05

Step1:注册Meta Box
首先,你需要使用add_meta_boxes钩子(hook)来注册一个meta_box。将以下代码添加到你的功能性插件或主题的functions.php文件中。


function my_custom_meta_box() {
    add_meta_box(
        'my_meta_box_id',          // Unique ID
        __('My Custom Meta Box'),  // Box title
        'my_meta_box_html',        // Content callback, must be of type callable
        'post'                     // Post type
    );
}
add_action('add_meta_boxes', 'my_custom_meta_box');

Step 2: 创建 Meta Box 内容
编写用于显示meta_box内容的回调函数。这个函数负责输出任何表单元素,用户会在此输入数据。


function my_meta_box_html($post) {
    // Add a nonce field so we can check for it later.
    wp_nonce_field('my_meta_box_nonce', 'meta_box_nonce');

    // 获取现存的值从数据库
    $value = get_post_meta($post->ID, '_my_meta_value_key', true);

    // 输出字段
    echo '<label for="my_meta_box_input"\>Description</label>';
    echo '<input type="text" id="my_meta_box_input" name="my_meta_box_input" value="' . esc_attr($value) . '" />';
}

Step 3: 加载样式表和脚本


function enqueue_admin_style_for_price($hook) {
    global $typenow;

    // ↓Post Type作为条件
    if ('post' === $typenow && ('post.php' == $hook || 'post-new.php' == $hook)) {
        // 使用正确的路径注册你的样式表。
        wp_register_style('price_wp_admin_css', get_stylesheet_directory_uri() . '/css/admin-price.css', false, version_num());
        // 排队你的样式表。
        wp_enqueue_style('price_wp_admin_css');
        // 使用正确的路径注册你的脚本文件。
        wp_register_script('price_wp_admin_js', get_stylesheet_directory_uri() . '/js/admin-price.js', array('jquery'), version_num(), true);
        // 排队你的脚本文件。
        wp_enqueue_script('price_wp_admin_js');
    }
}
// 添加到WordPress的'admin_enqueue_scripts'动作。
add_action('admin_enqueue_scripts', 'enqueue_admin_style_for_price');

Step 4: 保存 Meta Box 数据


function my_save_meta_box_data($post_id) {
    // 检查nonce安全性验证
    if (!isset($_POST['meta_box_nonce']) || !wp_verify_nonce($_POST['meta_box_nonce'], 'my_meta_box_nonce')) {
        return;
    }

    // 检查这次提交是否不是自动保存的草稿.
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }

    // 检查用户权限
    if (!current_user_can('edit_post', $post_id)) {
        return;
    }

    // 确保有数据被发送.
    if (!isset($_POST['my_meta_box_input'])) {
        return;
    }

    // 清理输入数据并保存它
    $my_data = sanitize_text_field($_POST['my_meta_box_input']);
    update_post_meta($post_id, '_my_meta_value_key', $my_data);
}
add_action('save_post', 'my_save_meta_box_data');

以上代码提供了在WordPress中创建和使用meta_boxes的基本框架。你可以通过注册具有不同字段类型的meta_box,比如下拉菜单、图片上传器、颜色选取器等,为你的帖子类型添加更多自定义数据字段。
确保所有自定义字段的名称都是唯一的,而且保存数据时进行了适当的权限检查和数据清洗,以避免安全漏洞。

如果my_meta_box_input是一个数组,你需要更改两个地方的代码:HTML表单元素的显示和数据保存逻辑。这里是如何修改上述示例的:

Step 2: 修改回调函数以显示数组类型的字段
如果你有多个输入字段或者一个字段接收多值,确保每个元素的name属性以数组形式命名,例如name=”my_meta_box_input[]”。


function my_meta_box_html($post) {
    // Add a nonce field so we can check for it later.
    wp_nonce_field('my_meta_box_nonce', 'meta_box_nonce');

    // 获取现存的值从数据库
    $values = get_post_meta($post->ID, '_my_meta_value_key', true);
    if (!is_array($values)) {
        $values = array();
    }

    // 输出字段
    foreach ($values as $index => $value) {
        echo '<label for="my_meta_box_input_' . $index . '">Description</label>';
        echo '<input type="text" id="my_meta_box_input_' . $index . '" name="my_meta_box_input[]" value="' . esc_attr($value) . '" />';
    }
    // 添加一个按钮用来添加新的输入框(可用JavaScript实现)
    echo '<button id="add_new_input">Add New</button>';

    // 务必也为上面的按钮添加 JavaScript 脚本以便能动态添加新的输入桜
}

Step 4: 修改保存逻辑来处理数组
在保存时,你需要对$_POST[‘my_meta_box_input’]做一个循环操作,以遍历所有的值。然后对每个值进行清理并保存。


function my_save_meta_box_data($post_id) {
    // 省略安全检查和权限检查代码...

    // 确保有数据被发送.
    if (isset($_POST['my_meta_box_input']) && is_array($_POST['my_meta_box_input'])) {
        // 清理输入数据
        $my_data = array_map('sanitize_text_field', $_POST['my_meta_box_input']);
        
        // 保存它
        update_post_meta($post_id, '_my_meta_value_key', $my_data);
    } else {
        // 如果没有接收到数据或者不是期待的数组,则删除meta key
        delete_post_meta($post_id, '_my_meta_value_key');
    }
}
add_action('save_post', 'my_save_meta_box_data');

要注意,update_post_meta()函数在处理单一键值对时会自动序列化和反序列化数组数据。因此,在保存一个数组时不需要额外的序列化步锤。

此外,在实际应用中,你可能还需要考虑添加和删除字段的用户界面逻辑,典型情况下使用JavaScript来动态增加或移除输入框。

技巧
Step2中使用了get_post_meta方法获得当前POST的meta数据,如果当前POST有多种类的meta情报的话,如果只想获得某个特定种类的meta数据的话,这个方法就不太适用了。
可以使用SQL文的方式获取你想要的meta数据。


function getPostMeta($post_id, $meta_key_pattern) {
  global $wpdb;

  $query = "SELECT meta_key, meta_value FROM {$wpdb->postmeta} WHERE post_id = {$post_id} and meta_key LIKE '{$meta_key_pattern}'";
  $results = $wpdb->get_results($query, ARRAY_A);
  $key_value_pairs = array();
  
  foreach ( $results as $row ) {
      $key_value_pairs[$row['meta_key']] = maybe_unserialize($row['meta_value']);
  }
  return $key_value_pairs;
}

批量删除特定的meta


function deletePriceMeta($post_id, $meta_key_pattern) {
  global $wpdb;

  $query = "SELECT DISTINCT meta_key FROM {$wpdb->postmeta} WHERE post_id = {$post_id} and meta_key LIKE '{$meta_key_pattern}'";
  $meta_keys = $wpdb->get_col($query);

  if (!empty($meta_keys)) {
      foreach ($meta_keys as $meta_key) {
          delete_post_meta($post_id, $meta_key);
      }
  }
}

Related Posts