欢迎光临
我们一直在努力

使用WordPress REST API创建WordPress设置页面

WordPress REST API的许多重要用途之一就是改善您的插件或主题设置屏幕。添加自定义REST API端点后,通过AJAX获取保存的设置并通过AJAX(即无额外页面刷新)保存设置将变得更加简单。

使用WordPress REST API代替admin-ajax不仅性能更高,而且还可以使WordPress核心在清理和验证方面完成大部分繁重的工作。

在本文中,我们将逐步完成创建设置表单页面的每个步骤,并使用WordPress REST API处理该表单。

添加设置页面

在开始设计设置页面之前,我们需要向WordPress仪表板添加菜单或子菜单项,您可以在其中放置设置表单。在此页面上,您将需要加载CSS和JavaScript文件。

这是一个入门类:

<?php
class Apex_Menu {
	/**
	 * Menu slug
	 *
	 * @var string
	 */
	protected $slug = 'apex-menu';
	/**
	 * URL for assets
	 *
	 * @var string
	 */
	protected $assets_url;
	/**
	 * Apex_Menu constructor.
	 *
	 * @param string $assets_url URL for assets
	 */
	public function __construct( $assets_url ) {
		$this->assets_url = $assets_url;
		add_action( 'admin_menu', array( $this, 'add_page' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'register_assets' ) );
	}
	/**
	 * Add CF Popup submenu page
	 *
	 * @since 0.0.3
	 *
	 * @uses "admin_menu"
	 */
	public function add_page(){
		add_menu_page(
			__( 'Apex Page', 'text-domain' ),
			__( 'Apex Page', 'text-domain' ),
			'manage_options',
			$this->slug,
			array( $this, 'render_admin' ) );
	}
	/**
	 * Register CSS and JS for page
	 *
	 * @uses "admin_enqueue_scripts" action
	 */
	public function register_assets()
	{
		wp_register_script( $this->slug, $this->assets_url . '/js/admin.js', array( 'jquery' ) );
		wp_register_style( $this->slug, $this->assets_url . '/css/admin.css' );
		wp_localize_script( $this->slug, 'APEX', array(
			'strings' => array(
				'saved' => __( 'Settings Saved', 'text-domain' ),
				'error' => __( 'Error', 'text-domain' )
			),
			'api'     => array(
				'url'   => esc_url_raw( rest_url( 'apex-api/v1/settings' ) ),
				'nonce' => wp_create_nonce( 'wp_rest' )
			)
		) );
	}
	/**
	 * Enqueue CSS and JS for page
	 */
	public function enqueue_assets(){
		if( ! wp_script_is( $this->slug, 'registered' ) ){
			$this->register_assets();
		}
		wp_enqueue_script( $this->slug );
		wp_enqueue_style( $this->slug );
	}
	/**
	 * Render plugin admin page
	 */
	public function render_admin(){
		$this->enqueue_assets();
		echo 'Put your form here!';
	}
}

在此类中,我使用add_menu_page创建一个顶层菜单,但是您可能希望根据需要使用add_sub_menu创建子菜单。

这里有两件事要注意。

首先是我们如何使用wp_localize_script()。每当加载第一个参数中指定的脚本时,此函数都可以为您提供一种使用PHP创建全局作用域JavaScript变量的方法。最初是为了向浏览器提供翻译后的本地化字符串而设计的。这就是我们使用它的一部分-提供可翻译的成功和错误消息。但是,它也可以用于传递动态值,例如当前站点的URL,在这种情况下为REST API终结点和随机数。我们将在JavaScript中需要所有这些功能,但是对于每个站点,它都是不同的,因此我们必须使用PHP即时生成它。

另外,请注意,脚本的根URL作为对类的依赖关系而传入。我喜欢这样做,因为该URL可能会在插件或主题的其他地方使用,并且我希望在一个地方更改或过滤整个插件。

实例化类时,需要指定该URL。这样做的一个好地方是在根插件文件中,使用plugin_dir_url()将生成正确的URL。让我们看一下设置它的主要插件文件:

<?php
/**
 * Plugin Name: Apex Plugin
 */
add_action( 'init', function(){
	$assets_url = plugin_dir_url( __FILE__ );
	//Setup menu
	if( is_admin() ){
		new Apex_Menu( $assets_url );
	}
	//Setup REST API
});

在此,我们使用“init”操作加载此类。我为REST API端点保留了一个占位符,一旦插件屏幕准备就绪,我们将使用它来保存数据。

设置表单

我不会对设置表单本身太深入,我可以为此写一整个系列。取而代之的是,我们仅添加两个字段来查看一些重要的内容。然后,我们可以编写JavaScript将表单值发送回服务器。

这是“render_admin”方法,使用具有两个字段的字段进行了更新:

/**
 * Render plugin admin page
 */
public function render_admin(){
    $this->enqueue_assets();
    ?>
    <form id="apex-form">
        <div id="feedback">
        </div>
        <div>
            <label for="industry">
                <?php esc_html_e( 'Industry', 'text-domain' ); ?>
            </label>
            <input id="industry" type="text" />
        </div>
        <div>
            <label for="amount">
                <?php esc_html_e( 'Amount', 'text-domain' ); ?>
            </label>
            <input id="amount" type="number" min="0" max="100" />
        </div>
        <?php submit_button( __( 'Save', 'text-domain' ) ); ?>
    </form>

    <?php
}

我确保每个字段都有一个ID。这将允许我使用jQuery.val()定位每个对象以获取其值。这对于保持我们的HTML语义也很重要,因为字段标签的属性必须与字段ID相对应。我还给了表单一个ID,并添加了一个ID为“feedback”的空元素,我们可以在其中动态放置保存或错误消息。

同样,您的表单可能会更复杂,但让我们开始吧。

添加REST API路由

在编写任何JavaScript通过AJAX将数据发送到服务器之前,我们需要为其提供REST API路由。我为此写了很多,但是值得通过一个非常简单的带有GETPOST端点的自定义路由。

分离业务逻辑

我坚信REST API路由的类应仅与处理请求有关,而与这些请求所需的业务逻辑无关。在这种情况下,“业务逻辑”是指读写实际设置。首先,让我们创建一个可以处理此问题的类。

此类将是带有一些基本验证的get_option()update_option()的简单包装。此类具有get_settings()方法,该方法获取保存的值,然后使用wp_parse_args()填充我们希望它具有的已保存数组的所有缺失索引。它还具有一个save_settings()方法,该方法确保只有要保存的数组的白名单键才在要保存的最终数组中。

<?php
class Apex_Settings {
	/**
	 * Option key to save settings
	 *
	 * @var string
	 */
	protected static $option_key = '_apex_settings';
	/**
	 * Default settings
	 *
	 * @var array
	 */
	protected static $defaults = array(
		'industry' => 'lumber',
		'amount' => 42
	);
	/**
	 * Get saved settings
	 *
	 * @return array
	 */
	public static function get_settings(){
		$saved = get_option( self::$option_key, array() );
		if( ! is_array( $saved ) || ! empty( $saved )){
			return self::$defaults;
		}
		return wp_parse_args( $saved, self::$defaults );
	}
	/**
	 * Save settings
	 *
	 * Array keys must be whitelisted (IE must be keys of self::$defaults
	 *
	 * @param array $settings
	 */
	public static function save_settings( array  $settings ){
		//remove any non-allowed indexes before save
		foreach ( $settings as $i => $setting ){
			if( ! array_key_exists( $setting, self::$defaults ) ){
				unset( $settings[ $i ] );
			}
		}
		update_option( self::$option_key, $settings );
	}
}

REST API路由

现在,我们有了一种读写方法,可以通过任何方式寻址,让我们创建一个REST API路由,以充当其RESTful接口。该路由将具有GET和POST端点。

如果您从未创建过自定义的REST API终结点,建议您阅读文档。我还介绍过与该主题相关的Torque文章和WordPress TV talks: 精选的链接列表  。

这是REST API路由类:

<?php
class Apex_API {
	/**
	 * Add routes
	 */
	public function add_routes( ) {
		register_rest_route( 'apex-api/v1', '/settings',
			array(
				'methods'         => 'POST',
				'callback'        => array( $this, 'update_settings' ),
				'args' => array(
					'industry' => array(
						'type' => 'string',
						'required' => false,
						'sanitize_callback' => 'sanitize_text_field'
					),
					'amount' => array(
						'type' => 'integer',
						'required' => false,
						'sanitize_callback' => 'absint'
					)
				),
				'permissions_callback' => array( $this, 'permissions' )
			)
		);
		register_rest_route( 'apex-api/v1', '/settings',
			array(
				'methods'         => 'GET',
				'callback'        => array( $this, 'get_settings' ),
				'args'            => array(
				),
				'permissions_callback' => array( $this, 'permissions' )
			)
		);
	}
	/**
	 * Check request permissions
	 *
	 * @return bool
	 */
	public function permissions(){
		return current_user_can( 'manage_options' );
	}
	/**
	 * Update settings
	 *
	 * @param WP_REST_Request $request
	 */
	public function update_settings( WP_REST_Request $request ){
		$settings = array(
			'industry' => $request->get_param( 'industry' ),
			'amount' => $request->get_param( 'amount' )
		);
		Apex_Settings::save_settings( $settings );
		return rest_ensure_response( Apex_Settings::get_settings())->set_status( 201 );
	}
	/**
	 * Get settings via API
	 *
	 * @param WP_REST_Request $request
	 */
	public function get_settings( WP_REST_Request $request ){
		return rest_ensure_response( Apex_Settings::get_settings());
	}
}

看一下,回调函数非常简单,因为它们只包装了我在上一节中创建的设置类。重要的是要了解,根据设计,设置类没有权限检查或清理操作。但是权限检查和清理非常重要。

这些REST API端点提供了这一点。POST方法为每个字段指定一个“ sanitize_callback”参数。这样,我可以相信数据在传入之前是安全的。而且,这两个路由都使用“permissions_callback”,因此只能通过具有“ manage_options”功能的路由来访问这些路由。跳过这些步骤中的任何一个都是危险的。

现在我们只需要在“rest_api_init”操作上实例化此类,以便存在端点。这又是主要的插件文件,对其进行了修改以实现此目的:

<?php
/**
 * Plugin Name: Apex Plugin
 */
add_action( 'init', function(){
	$assets_url = plugin_dir_url( __FILE__ );
	//Setup menu
	if( is_admin() ){
		new Apex_Menu( $assets_url );
	}
	//Setup REST API
});

在“设置”页面中使用REST API

现在我们有了端点,让我们在设置页面上使用它们。我们将编写两个AJAX调用。第一个将获取保存的设置,并使用这些设置更新表单。这将由页面加载触发。第二个将由表单保存按钮触发,并将用于更新设置。

在本教程的前面,我们告诉WordPress在此管理页面上加载JavaScript文件。现在该使用该文件了。

这是第一个AJAX调用的样子。它的工作是获取保存的设置并使用以下内容更新表单:

jQuery(function($) {
	
	$.ajax({
		method: 'GET',
		url: APEX.api.url
		beforeSend: function ( xhr ) {
			xhr.setRequestHeader( 'X-WP-Nonce', APEX.api.nonce );
		}
	}).then( function ( r ) {
		if( r.hasOwnProperty( 'industry' ) ){
			$( '#industry' ).val( r.industry );
		}

		if( r.hasOwnProperty( 'amount' ) ){
			$( '#amount' ).val( r.amount );
		}
	})

});

请注意此处的两个重要事项。首先,我使用之前通过wp_localize_script()设置的APEX全局对象来告诉jQuery请求什么URL。另外,我正在使用beforeSend()方法添加包含该对象中随机数的标头。否则,在API请求处理期间将不会认为用户已登录,因此我们的权限检查将失败。

API请求完成后,使用jQuery.val()将设置添加到表单字段。为了安全起见,我使用Object.hasOwnProperty()确保它们在响应中。这是很重要的验证,但是随着设置数量的增长而无法很好地扩展-这是我使用VueJS进行这种事情的众多原因之一。

现在,当您加载页面时,它应该获取已保存的设置(此时可能是默认值)并更新表单。很好,但是所有这些的真正意义在于能够更新设置。因此,我们将需要第二个AJAX调用,该调用将在提交表单时运行POST请求。

这是带有保存AJAX调用的更新后的JavaScript:

jQuery(function($) {

	$.ajax({
		method: 'GET',
		url: APEX.api.url,
		beforeSend: function ( xhr ) {
			xhr.setRequestHeader( 'X-WP-Nonce', APEX.api.nonce );
		}
	}).then( function ( r ) {
		if( r.hasOwnProperty( 'industry' ) ){
			$( '#industry' ).val( r.industry );
		}

		if( r.hasOwnProperty( 'amount' ) ){
			$( '#amount' ).val( r.amount );
		}
	});

	$( '#apex-form' ).on( 'submit', function (e) {
		e.preventDefault();
		var data = {
			amount: $( '#amount' ).val(),
			industry: $( '#industry' ).val()
		};

		$.ajax({
			method: 'POST',
			url: APEX.api.url,
			beforeSend: function ( xhr ) {
				xhr.setRequestHeader('X-WP-Nonce', APEX.api.nonce);
			},
			data:data
		}).then( function (r) {
			$( '#feedback' ).html( '<p>' + APEX.strings.saved + '</p>' );
		}).error( function (r) {
			var message = APEX.strings.error;
			if( r.hasOwnProperty( 'message' ) ){
				message = r.message;
			}
			$( '#feedback' ).html( '<p>' + message + '</p>' );

		})
	})
});

第二个调用非常相似,除了它使用POST并包装在与表单的commit事件绑定的闭包中。这样,它在表单提交时运行,我们可以防止该事件的默认操作发生。

您应该在这里查看成功和错误方法。它们用于将文本(位于APEX.string对象中)本地化的消息添加到#feedback元素中。该对象中的“错误”消息非常笼统。但是大多数失败的请求都会生成一条带有消息的响应。因此,如果已设置,我们将改用它。

 收藏 (0) 打赏

您可以选择一种方式赞助本站

支付宝扫一扫赞助

微信钱包扫描赞助

未经允许不得转载:源码猫 » 使用WordPress REST API创建WordPress设置页面

分享到: 更多 (0)
avatar

热门文章

  • 评论 抢沙发

    评论前必须登录!

    立即登录   注册

    切换注册

    登录

    忘记密码 ?

    您也可以使用第三方帐号快捷登录

    切换登录

    注册

    我们将发送一封验证邮件至你的邮箱, 请正确填写以完成账号注册和激活