WordPress中文开发手册

WordPress插件开发 — 服务器端PHP和入队

实现AJAX通信所需的服务器端PHP脚本有两个部分。 首先,我们需要在网页上排列jQuery脚本,并本地化jQuery脚本需要的任何PHP值。 其次是AJAX请求的实际处理。

入队脚本

本部分介绍了WordPress中AJAX的两大难点,它将经验丰富的编程人员新增至WordPress。 一个是需要排入脚本,以便获得元链接在页面的头部分中正确显示。 另一个是所有AJAX请求需要通过wp-admin / admin-ajax.php发送。 不要将请求直接发送到您的插件页面。

排队

使用函数wp_enqueue_script()让WordPress在页面的部分插入一个元链接到您的脚本。 不要在标题模板中硬编码这样的链接。 作为一个插件开发人员,您没有准备好访问标题模板,但是这个规则不管怎么说。

入队功能有三个参数。 第一个是用于在其他功能中引用脚本的任意标签或句柄。 第二个是脚本文件的完整URL。 为了便于携带,请使用plugins_url()来构建正确的URL。 如果你为插件之外的东西排队脚本,使用一些相关的功能创建一个正确的URL - 从来没有硬编码。 第三个参数是脚本依赖的任何脚本标记的数组。 由于我们使用jQuery发送一个AJAX请求,所以至少需要在数组中列出'jquery'。 始终使用数组,即使它是单个依赖项。 我们的示例的入队呼叫如下所示:

wp_enqueue_script( 'ajax-script',
    plugins_url( '/js/myjquery.js', __FILE__ ),
    array('jquery')
);

加载脚本时,您无法直接从插件代码页排入脚本。 脚本必须从几个动作钩子之一排队 - 哪一个取决于脚本需要链接到哪个页面。 对于管理页面,请使用admin_enqueue_scripts。 对于前端页面使用wp_enqueue_scripts,除了登录页面,在这种情况下使用login_enqueue_scripts。

admin_enqueue_scripts钩子将当前页面文件名传递给您的回调。 使用此信息仅将脚本排列在需要的页面上。 前端版本没有通过任何内容。 在这种情况下,使用模板标签(如is_home(),is_single()等)来确保您只需将脚本排列在需要的位置。 这是我们的示例的完整的入队代码:

add_action( 'admin_enqueue_scripts', 'my_enqueue' );
function my_enqueue( $hook ) {
    if( 'myplugin_settings.php' != $hook ) return;
    wp_enqueue_script( 'ajax-script',
        plugins_url( '/js/myjquery.js', __FILE__ ),
        array( 'jquery' )
    );
}

为什么我们在这里使用命名函数,但是使用jQuery的匿名函数?因为闭包最近才被PHP支持。 jQuery已经支持了很多时间。由于有些人可能仍在运行旧版本的PHP,因此我们总是使用命名函数来实现最大的兼容性。如果您有最新的PHP版本,并且仅针对您自己的安装开发,请继续使用闭包。

##注册与入队

您将在其他教程中看到宗教使用wp_register_script()的示例。这很好,但它的使用是可选的。什么是不可选的是wp_enqueue_script()。必须调用此函数才能使您的脚本文件在网页上正确链接。那么为什么要注册脚本?它创建一个有用的标签或句柄,您可以根据需要轻松地在代码的各个部分中引用该脚本。如果您只需要加载脚本,而不是在代码中的其他地方引用它,则无需注册。

##随机

您需要创建一个随机数,以便jQuery AJAX请求可以被验证为合法请求,而不是来自某个未知的坏行为者的潜在的恶意请求。只有你的PHP脚本和你的jQuery脚本才能知道这个值。收到请求后,您可以验证它是在此创建的相同值。这是为了创建一个我们的例子的随机数

$title_nonce = wp_create_nonce( 'title_example' );

参数title_example可以是任意任意的字符串。 建议字符串与所使用的内容相关,但它可以是适合您的任何东西。

##本地化

如果您从jQuery部分回想起,由jQuery创建的由jQuery创建的数据被传递给一个名为my_ajax_obj的全局对象。 在我们的示例中,此数据是一个随机数,并且是admin-ajax.php的完整URL。 分配对象属性和创建全局jQuery对象的过程称为本地化。 这是我们使用wp_localize_script()的示例中使用的本地化代码。

wp_localize_script( 'ajax-script', 'my_ajax_obj', array(
    'ajax_url' => admin_url( 'admin-ajax.php' ),
    'nonce'    => $title_nonce, // It is common practice to comma after
) );                // the last array item for easier maintenance

注意我们的脚本如何处理ajax脚本被使用,以便将全局对象分配给正确的脚本。 对象对我们的脚本是全局的,而不是所有的脚本。 也可以从用于排入脚本的同一个钩子调用本地化。 创建一个随机数也同样如此,尽管这个特定的功能可以在几乎任何地方被调用。 所有这些组合在一起的单个钩子回调看起来像这样:

add_action( 'admin_enqueue_scripts', 'my_enqueue' );
function my_enqueue( $hook ) {
    if( 'myplugin_settings.php' != $hook ) return;
    wp_enqueue_script( 'ajax-script',
        plugins_url( '/js/myjquery.js', __FILE__ ),
        array( 'jquery' )
    );
    $title_nonce = wp_create_nonce( 'title_example' );
    wp_localize_script( 'ajax-script', 'my_ajax_obj', array(
       'ajax_url' => admin_url( 'admin-ajax.php' ),
       'nonce'    => $title_nonce,
    ) );
}

AJAX行动

服务器端PHP代码的另一个主要部分是接收POSTed数据的实际AJAX处理程序,执行一些操作,然后将相应的响应发送回浏览器。 这采用WordPress动作钩子的形式。 您使用哪个挂钩标签取决于用户是否登录,并且您的jQuery脚本作为action:value传递的值是多少。

注意:$_GET , $_POST and $_COOKIE vs $_REQUEST

您可能已经使用一个或多个PHP超级全局变量(如$ _GET或$ _POST)从表单或Cookie(使用$ _COOKIE)检索值。也许你更喜欢$ _REQUEST,或至少看过它使用。这很酷 - 无论请求方法,POST或GET,它将具有表单值。适用于使用这两种方法的页面。除此之外,它还具有cookie值。一站式购物!其中有它的悲剧性缺陷。在名称冲突的情况下,cookie值将覆盖任何表单值。因此,糟糕的演员在他们的浏览器上制作一个假冒的cookie是非常容易的,这将覆盖您可能期望的请求的任何表单值。 $ _REQUEST是黑客将任意数据注入到表单值中的简单路径。要特别安全,坚持特定的变量,避免一切都适合。

由于我们的AJAX交换是用于插件的设置页面,所以用户必须登录。如果从jQuery部分回想起来,action:value是“my_tag_count”。这意味着我们的动作钩子标签将是wp_ajax_my_tag_count。如果我们的AJAX交换机被当前未登录的用户使用,则动作挂钩标签将是wp_ajax_nopriv_my_tag_count用于挂起动作的基本代码如下所示:

add_action( 'wp_ajax_my_tag_count', 'my_ajax_handler' );
function my_ajax_handler() {
    // Handle the ajax request
    wp_die(); // All ajax handlers die when finished
}

您的AJAX处理程序应该做的第一件事情是验证jQuery与check_ajax_referer()发送的随机数,该值应与脚本入队时本地化的值相同。

check_ajax_referer( 'title_example' );

提供的参数必须与之前提供的参数wp_create_nonce()相同。 如果随机数不检出,该函数就会死机。 如果这是一个真正的现在,现在使用它,这个价值不再是好的。 然后,您将生成一个新的并将其发送到回调脚本,以便它可以用于下一个请求。 但是由于WordPress的内容有二十四个小时的好处,所以你不需要做任何事情,但检查它。

##数据

随着nonce不可用,我们的处理程序可以处理由$ _POST ['title']中包含的jQuery脚本发送的数据。 我们可以使用update_user_meta()将用户的选择保存在用户元中。

update_user_meta( get_current_user_id(), 'title_preference', $_POST['title']);

然后,我们构建一个查询以获取所选标题标签的发布数。

$args = array(
    'tag' => $_POST['title'],
);
$the_query = new WP_Query( $args );

最后我们可以将响应发送回jQuery脚本。有几种传输数据的方法。在我们处理我们的例子的细节之前,我们来看一些选项。

XML

对XML的PHP​​支持留下了一些希望。幸运的是,WordPress提供了WP_Ajax_Response类,使任务更容易。 WP_Ajax_Response类将生成XML格式的响应,为标题设置正确的内容类型,输出响应xml,然后死 - 确保正确的XML响应。

JSON

这种格式是轻量级和易于使用的,WordPress提供的wp_send_json函数来json编码您的响应,打印它,并死 - 有效地替换WP_Ajax_Response。 WordPress还提供了wp_send_json_success和wp_send_json_error函数,这些函数允许在JS中触发适当的done()或fail()回调。

##其他

只要发送者和接收者协调一致,就可以传输任何你喜欢的数据。诸如逗号分隔或制表符分隔的文本格式是许多可能性之一。对于少量的数据,发送原始流可能是足够的。这就是我们将使用我们的例子 - 我们将发送实际的替换HTML,没有别的。

echo $_POST['title'].' ('.$the_query->post_count.') ';

在现实世界的应用程序中,您必须考虑到由于某种原因可能会失败的可能性 - 例如,数据库服务器可能已关闭。 响应应该允许这种偶然性,并且接收响应的jQuery脚本应该相应地行动,或许告诉用户稍后再试。

die

当处理程序完成所有任务时,它需要死机。 如果您使用WP_Ajax_Response或wp_send_json *函数,则会自动为您处理。 如果没有,只需使用WordPress wp_die()函数。

wp_die();
// That's all folks!

AJAX处理者总结

我们的示例的完整AJAX处理程序如下所示:

//JSON
function my_ajax_handler() {
    check_ajax_referer( 'title_example' );
    update_user_meta( get_current_user_id(), 'title_preference', $_POST['title'] );
    $args = array(
        'tag' => $_POST['title'],
    );
    $the_query = new WP_Query( $args );
        wp_send_json( $_POST['title'] . ' (' . $the_query->post_count . ') ' );
}

//Other
function my_ajax_handler() {
    check_ajax_referer( 'title_example' );
    update_user_meta( get_current_user_id(), 'title_preference', $_POST['title'] );
    $args = array(
        'tag' => $_POST['title'],
    );
    $the_query = new WP_Query( $args );
    echo $_POST['title'].' ('.$the_query->post_count.') ';
    wp_die(); // All ajax handlers should die when finished
}
Tags