跳转到主要内容

自定义meta元数据框

什么是元框?

当用户编辑帖子时,编辑屏幕由几个默认框组成:编辑器、发布、类别、标签等。这些框是元框。插件可以将自定义元框添加到任何帖子类型的编辑屏幕。

自定义元框的内容通常是 HTML 表单元素,用户在其中输入与插件用途相关的数据,但内容实际上可以是您想要的任何 HTML。

为什么使用元框?

元框是方便、灵活、模块化的编辑屏幕元素,可用于收集与正在编辑的帖子相关的信息。您的自定义元框将与所有其他帖子相关信息位于同一屏幕上;这样就建立了明确的关系。

元框可以轻松地对不需要查看的用户隐藏,并显示给需要查看的用户。用户可以在编辑屏幕上排列元框。用户可以自由地以适合自己的方式排列编辑屏幕,从而使用户可以控制自己的编辑环境。

警报:本页上的所有示例仅用于说明目的。该代码不适合生产环境。
诸如保护输入用户功能随机数国际化等操作已被有意省略。请务必始终解决这些重要的操作。

 

添加元框

要创建元框,请使用add_meta_box() 函数并将其执行插入到add_meta_boxes操作挂钩中。

以下示例是向post编辑屏幕和wporg_cpt编辑屏幕添加元框。


function wporg_add_custom_box() {
	$screens = [ 'post', 'wporg_cpt' ];
	foreach ( $screens as $screen ) {
		add_meta_box(
			'wporg_box_id',                 // Unique ID
			'Custom Meta Box Title',      // Box title
			'wporg_custom_box_html',  // Content callback, must be of type callable
			$screen                            // Post type
		);
	}
}
add_action( 'add_meta_boxes', 'wporg_add_custom_box' );

wporg_custom_box_html函数将保存元框的 HTML。

以下示例添加表单元素、标签和其他 HTML 元素。


function wporg_custom_box_html( $post ) {
	?>
	<label for="wporg_field">Description for this field</label>
	<select name="wporg_field" id="wporg_field" class="postbox">
		<option value="">Select something...</option>
		<option value="something">Something</option>
		<option value="else">Else</option>
	</select>
	<?php
}

笔记:请注意,元框中没有提交按钮。POST元框 HTML 包含在编辑屏幕的表单标签内,当用户单击“发布”或“更新”按钮时,包括元框值在内的所有发布数据都会传输。

此处显示的示例仅包含一个表单字段,即一个下拉列表。您可以根据需要在任何特定元框中创建任意数量的元数据。如果您有很多字段要显示,请考虑使用多个元框,将每个元框中相似的字段分组在一起。这有助于使页面更有条理、更具视觉吸引力。

获取值

要检索保存的用户数据并使用它,您需要从最初保存它的位置获取它。如果它存储在表中,您可以使用get_post_meta()postmeta获取数据。

以下示例使用基于保存的元框值的预填充数据增强了先前的表单元素。您将在下一节中了解如何保存元框值。

function wporg_custom_box_html( $post ) {
	$value = get_post_meta( $post->ID, '_wporg_meta_key', true );
	?>
	<label for="wporg_field">Description for this field</label>
	<select name="wporg_field" id="wporg_field" class="postbox">
		<option value="">Select something...</option>
		<option value="something" <?php selected( $value, 'something' ); ?>>Something</option>
		<option value="else" <?php selected( $value, 'else' ); ?>>Else</option>
	</select>
	<?php
}

有关selected() 函数的更多信息。

 

保存价值

保存或更新帖子类型时,会触发多个操作,其中任何操作都可能适合挂钩以保存输入的值。在此示例中,我们使用save_post操作挂钩,但其他挂钩可能更适合某些情况。请注意,save_post对于单个更新事件可能会多次触发。相应地构建保存数据的方法。

您可以将输入的数据保存在任何您想要的地方,甚至可以在 WordPress 之外保存。由于您可能正在处理与帖子相关的数据,因此表postmeta通常是存储数据的好地方。

以下示例将wporg_field_wporg_meta_key元键中保存字段值,该元键是隐藏的。

 

function wporg_save_postdata( $post_id ) {
	if ( array_key_exists( 'wporg_field', $_POST ) ) {
		update_post_meta(
			$post_id,
			'_wporg_meta_key',
			$_POST['wporg_field']
		);
	}
}
add_action( 'save_post', 'wporg_save_postdata' );

在生产代码中,请记住遵循信息框中概述的安全措施!

幕后花絮

您通常不需要关心幕后发生的事情。添加此部分是为了完整性。

当帖子编辑屏幕想要显示添加到其中的所有元框时,它会调用 do_meta_boxes () 函数。该函数循环遍历所有元框并调用callback与每个元框关联的元框。
在每次调用之间,添加中间标记(例如 div、标题等)。

删除元框

要从编辑屏幕中删除现有元框,请使用remove_meta_box() 函数。传递的参数必须与用于使用add_meta_box()添加元框的参数完全匹配。

要删除默认元框,请检查所使用参数的源代码。默认的add_meta_box() 调用是从wp-includes/edit-form-advanced.php.

实施变体

到目前为止,我们一直在使用实现元框的程序技术。许多插件开发人员发现需要使用各种其他技术来实现元框。

面向对象编程

使用 OOP 添加元框很容易,并且使您不必担心全局命名空间中的命名冲突。
为了节省内存并更容易实现,以下示例使用具有静态方法的抽象类。

abstract class WPOrg_Meta_Box {


	/**
	 * Set up and add the meta box.
	 */
	public static function add() {
		$screens = [ 'post', 'wporg_cpt' ];
		foreach ( $screens as $screen ) {
			add_meta_box(
				'wporg_box_id',          // Unique ID
				'Custom Meta Box Title', // Box title
				[ self::class, 'html' ],   // Content callback, must be of type callable
				$screen                  // Post type
			);
		}
	}


	/**
	 * Save the meta box selections.
	 *
	 * @param int $post_id  The post ID.
	 */
	public static function save( int $post_id ) {
		if ( array_key_exists( 'wporg_field', $_POST ) ) {
			update_post_meta(
				$post_id,
				'_wporg_meta_key',
				$_POST['wporg_field']
			);
		}
	}


	/**
	 * Display the meta box HTML to the user.
	 *
	 * @param WP_Post $post   Post object.
	 */
	public static function html( $post ) {
		$value = get_post_meta( $post->ID, '_wporg_meta_key', true );
		?>
		<label for="wporg_field">Description for this field</label>
		<select name="wporg_field" id="wporg_field" class="postbox">
			<option value="">Select something...</option>
			<option value="something" <?php selected( $value, 'something' ); ?>>Something</option>
			<option value="else" <?php selected( $value, 'else' ); ?>>Else</option>
		</select>
		<?php
	}
}

add_action( 'add_meta_boxes', [ 'WPOrg_Meta_Box', 'add' ] );
add_action( 'save_post', [ 'WPOrg_Meta_Box', 'save' ] );

Ajax

由于元框的 HTML 元素位于form编辑屏幕的标签内,因此默认行为是在用户提交页面后$_POST从超级全局解析元框值。

您可以使用 AJAX 增强默认体验;这允许根据用户输入和行为执行操作;无论他们是否提交了页面。

定义触发器

首先,您必须定义触发器,这可以是链接单击、值更改或任何其他 JavaScript 事件。

在下面的示例中,我们将定义change为执行 AJAX 请求的触发器。

/*jslint browser: true, plusplus: true */
(function ($, window, document) {
    'use strict';
    // execute when the DOM is ready
    $(document).ready(function () {
        // js 'change' event triggered on the wporg_field form field
        $('#wporg_field').on('change', function () {
            // our code
        });
    });
}(jQuery, window, document));

客户端代码

接下来,我们需要定义触发器要做什么,换句话说,我们需要编写客户端代码。

在下面的示例中,我们将发出POST请求,响应将是成功或失败,这将表明 的值wporg_field是有效的。

/*jslint browser: true, plusplus: true */
(function ($, window, document) {
    'use strict';
    // execute when the DOM is ready
    $(document).ready(function () {
        // js 'change' event triggered on the wporg_field form field
        $('#wporg_field').on('change', function () {
            // jQuery post method, a shorthand for $.ajax with POST
            $.post(wporg_meta_box_obj.url,                        // or ajaxurl
                   {
                       action: 'wporg_ajax_change',                // POST data, action
                       wporg_field_value: $('#wporg_field').val(), // POST data, wporg_field_value
                       post_ID: jQuery('#post_ID').val()           // The ID of the post currently being edited
                   }, function (data) {
                        // handle response data
                        if (data === 'success') {
                            // perform our success logic
                        } else if (data === 'failure') {
                            // perform our failure logic
                        } else {
                            // do nothing
                        }
                    }
            );
        });
    });
}(jQuery, window, document));

 

wporg_meta_box_obj我们从下一步将创建的 JavaScript 自定义对象动态获取 WordPress AJAX 文件 URL 。

笔记:如果您的元框仅需要 WordPress AJAX 文件 URL;您可以使用预定义的 JavaScript 变量,而不是创建新的自定义 JavaScript 对象ajaxurl

仅在 WordPress 管理中可用。在执行任何逻辑之前确保它不为空。

排队客户端代码

下一步是将我们的代码放入脚本文件中并将其排队到我们的编辑屏幕上。

在下面的示例中,我们将向以下帖子类型的编辑屏幕添加 AJAX 功能:post、wporg_cpt。

脚本文件将驻留在/plugin-name/admin/meta-boxes/js/admin.jsplugin-name插件文件夹中,即
/plugin-name/plugin.php调用该函数的文件。

function wporg_meta_box_scripts()
{
    // get current admin screen, or null
    $screen = get_current_screen();
    // verify admin screen object
    if (is_object($screen)) {
        // enqueue only for specific post types
        if (in_array($screen->post_type, ['post', 'wporg_cpt'])) {
            // enqueue script
            wp_enqueue_script('wporg_meta_box_script', plugin_dir_url(__FILE__) . 'admin/meta-boxes/js/admin.js', ['jquery']);
            // localize script, create a custom js object
            wp_localize_script(
                'wporg_meta_box_script',
                'wporg_meta_box_obj',
                [
                    'url' => admin_url('admin-ajax.php'),
                ]
            );
        }
    }
}
add_action('admin_enqueue_scripts', 'wporg_meta_box_scripts');

服务器端代码

最后一步是编写将处理请求的服务器端代码。

// The piece after `wp_ajax_`  matches the action argument being sent in the POST request.
add_action( 'wp_ajax_wporg_ajax_change', 'my_ajax_handler' );
 
/**
 * Handles my AJAX request.
 */
function my_ajax_handler() {
    // Handle the ajax request here
    if ( array_key_exists( 'wporg_field_value', $_POST ) ) {
        $post_id = (int) $_POST['post_ID'];
        if ( current_user_can( 'edit_post', $post_id ) ) {
            update_post_meta(
                $post_id,
                '_wporg_meta_key',
                $_POST['wporg_field_value']
            );
        }
    }
 
    wp_die(); // All ajax handlers die when finished
}

 

最后提醒一下,本页所示的代码缺少考虑安全性的重要操作。确保您的生产代码包含此类操作。

有关 AJAX 的更多信息,请参阅手册的 AJAX 章节Codex 。

更多信息