WordPress AJAX主题实例 (以jQuery为例)

0

一般使用jQuery实现AJAX的情况

如果你曾经在一般网页上实作过ajax效果,尤其是使用jQuery (无论是用load(), post()或ajax()…等方式),你一定可以在阅读本文后很快就理解WP是怎么处理ajax效果的。

先来看看一个利用AJAX来载入资料的情境:以jQuery实现AJAX为例,我们通常会以送出GET或POST请求的方式,带上一些参数资料,再丢给一个负责处理的目标网址,而这个目标网址的PHP文件会接收我们传过去的参数,作为存取数据库资料的条件,接着将资料输出,如此就达成非同步载入资料的效果。

wordpress_ajax

在WP实现AJAX的概述

在WP实现ajax的效果,大致也是采用这种方式,但是无论前台、后台中的任何一个页面,都统一要将参数资料丢到 /wp-admin/admin-ajax.php 这个目标网址。当你把资料丢过去之后,你就可以在functions.php或者plugin里利用hook function,去取得丢过来的参数资料,接着如果你要进行数据库操作,就宣告$wpdb来做事就行了。

请注意,本文以下的例子为求容易理解原理,因此没有考虑最佳的实现方式,建议你应该在理解运作原理后多多参考其他更好的做法。

在主题中实现AJAX效果

为求方便讲解,我们直接修改主题中的 header.php (请先确定你的WP网站已有载入jQuery),在里加入:

<script>
 jQuery(function(){
   // 按下按钮后开始送出POST要求
   $('.btn_ajax').click(function () {
     $.post('<?php echo admin_url( 'admin-ajax.php' );?>', {
       action: 'my_ajax_action', // 自取一个action的名称
       post_id: $('#my_id').val() // 附上的参数
     }, function(data) {
       alert(data); // 当AJAX处理完毕,就把回传的资料alert出来
     });
   });
 });
</script>

里头的PHP函数:admin_url(admin-ajax.php)其实就是传回/wp-admin/admin-ajax.php的完整网址;然后我们要自己取一个action的名称,之所以叫action,就是表示这里的名称会对应到等会要写的hook function的名称。接着在header.php下方之后找地方加入:

<input type="text" value="mrmu" id="my_id">
<input type="button" class="btn_ajax" value="按我">

如此前端的配置就完成了,接着到 functions.php找地方加入:

1
2
3
4
5
6
7
add_action( 'wp_ajax_my_ajax_action', 'ajax_action_stuff' ); // 针对已登录的使用者
add_action( 'wp_ajax_nopriv_my_ajax_action', 'ajax_action_stuff' ); // 针对未登录的使用者
function ajax_action_stuff() {
 $post_id = $_POST['post_id']; // 从ajax POST的请求取得的参数资料
 echo $post_id; // 单纯的印出来,如此前端就会收到
 die(); // 一定要加这行,才会完整的处理ajax请求
}

观察一下上述的代码,首先我们加入两个action hook,第一个是wp_ajax_my_ajax_action,去掉前缀字’wp_ajax_’,剩下的my_ajax_action有没有很眼熟?就是我们在前端自取的action名称。
第二个action hook也是拿了我们自取的action加上前缀字’wp_ajax_nopriv_’,代表若使用者未登录,就会触发这个hook。

当wp_ajax的hook function成功被触发时,我们就能拿到前端丢过来的参数资料,也就能拿它来作为条件,进一步去存取资料库,再回传值至前端,达成ajax的效果。

不过,进一步的看这个例子,其实是很多缺点的。我们的例子是把前端js的部份写在header.php,所以可以精简一下使用php function来取得admin-ajax.php的完整网址,如果要把这段js程式码整理到.js档内,就要在functions.php这样写了:

add_action('init', 'add_my_ajax_script');
function add_my_ajax_script(){
 wp_enqueue_script( 'my_ajax_script', get_stylesheet_directory_uri().'/js/script.js', array('jquery'), 1.0 );
 wp_localize_script( 'my_ajax_script', 'my_ajax_obj', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) ); // 先将ajaxurl变数设定好
}

如此我们就可以在主题目录下的/js/script.js中利用my_ajax_obj.ajaxurl取得admin-ajax.php的完整网址:

(function($) {
 $(function() {
   $('.target').click(function () {
     $.post(my_ajax_obj.ajaxurl, { //取得admin-ajax.php的完整网址
       action: 'ajax_action',
       post_id: $(this).find('input.post_id').attr('value')
     }, function(data) {
       alert(data); // alerts
     });
   });
 });
})(jQuery);

在后台实现AJAX效果

在需要实现的页面上,注册需要的style及script

要在wp后台完成ajax效果,我们必须要先在目标页面加入我们自订的JS。你可能想在发表文章页、编辑文章页加入ajax效果,或者自订一个后台设定页面,然后在里头使用ajax效果。

你当然可以直接用admin_init这个hook,来将所需的js及css档加入,但如此一来在后台所有页面都会汇入你自订的js及css档。讲究一点的话,你应该只针对想要有效果的页面来汇入,如果是发表/编辑文章页面,可以利用这两个action hook:

add_action('load-post.php', 'reg_admin_scripts_and_styles' ); // 文章编辑页
add_action('load-post-new.php', 'reg_admin_scripts_and_styles' ); // 文章发表页

若是自行建立新的后台页面,则可以在呼叫建立页面的function后取得page_hook_suffix,并利用它来加入所需的js及css,以建立一个「设定」页面来举例:

add_action('admin_menu', '__add_menu' );
function __add_menu()
{
  if (function_exists('add_options_page'))
  {
    $my_opt_page_hook_suffix = add_options_page(
      'Product', //Page Title
      'Tcc CP Product', //Menu Title
      'editor', // Capability
      'my_menu_slug', // Menu Slug
      'panel_ui_rendering' // UI Function
    );
 
    // 在此页enqueue页首script及styles
    add_action("load-{$my_opt_page_hook_suffix}", 'reg_admin_scripts_and_styles' );
  }
}

然后你就可以建立reg_admin_scripts_and_style 这个function,来将所需的scripts及styles注册及enqueue。

接受及发送资料给WP

针对特定页面来汇入所需的js后,就可以进入正题了,要怎么完成ajax效果?跟前台一样。

首先,汇入的 js 里,无论使用jQuery load, ajax, post,都一定要 POST 一个名为action的变数给WP已预先定义的网址:ajaxurl。
跟前台稍微不同的地方是,后台的ajaxurl变数,已经先帮我们取得admin-ajax.php的完整网址了,所以直接拿来用就行了。
action变数的内容需要自订一个名称,而WP就会以这个名称偷偷建立对应的hook action。

除了post action外,可以再自带需要的参数进去,通常会建立一个名为data的js object,举例来说,你的js档内相关处理的code可能会长这样:

(function($) {
  $(function() {
    // 要POST的资料
    var data = {
      action: 'list_rec',
      arg1: 'arg1 的资料',
      arg2: 'arg2 的资料',
      arg3: 'arg3 的资料',
    };
    // 自 WP 2.8 起ajaxurl 已被定义在 admin header 并指向 admin-ajax.php
    $('#ajax_content_sec').load(ajaxurl, data, function(){
    // 已将data物件POST到ajaxurl,ajax 载入成功!
      alert('载入完毕!');
    });
  });
})(jQuery);

接着在functions.php或plugin里,就可以直接add你在js里定义的那个action,只是要记得加上前缀字wp_ajax_:

add_action('wp_ajax_list_rec', 'list_rec_callback');
function list_rec_callback() {
  // 读取POST资料
  $arg1 = $_POST['arg1'];
  $arg2 = $_POST['arg2'];
  $arg3 = $_POST['arg3'];
 
  global $wpdb; //可以拿POST来的资料作为条件,捞DB的资料来作显示
  echo 'arg1: ' . $arg1 . '&lt;br&gt;arg2: '. $arg2 . '&lt;br&gt;arg3: '. $arg3;
  die(); // this is required to return a proper result
}

有了这样的架构,我们就可以实作ajax效果了。最普遍的例子就是在使用者按下连结或按钮后,会出现Loading的动画,然后某个区块就产生一堆资料。

这样的行为,需要在js收集好「条件」,可以在js里针对某个连结来bind一个click事件,然后将dom里的资料(或url上的GET参数)拿来放进上述的data物件里,再作ajax post。

post到wp_ajax 对应的hook function里时,就可以拿到这些「条件」,接着在wp_ajax function里利用$wpdb捞出所需的资料,再作输出就打完收工了。

翻译自MRMU 未经许可禁止转载

发表评论

您的邮箱不会公开,当您的评论有新的回复时,会通过您填写的邮箱向您发送评论内容。 必填字段 *

为何看不到我发布的评论?

正在提交, 请稍候...