WordPress AJAX佈景實作 (以jQuery為例)
| 2012/06/12 | 1 則迴響
一般使用jQuery實作AJAX的情況
如果你曾經在一般網頁上實作過ajax效果,尤其是使用jQuery (無論是用load(), post()或ajax()…等方式),你一定可以在閱讀本文後很快就理解WP是怎麼處理ajax效果的。
先來看看一個利用 jQuery Ajax 函式傳遞資料到後端的例子:
$.ajax({ type: 'POST', url: 'https://my_ajax_url.test/ajax.php', data: { arg: 'arg data' }, success: function(res) { console.log(res); // 後端回傳結果 }, error:function (jqXHR, ajaxOptions, thrownError){ console.log(ajaxOptions+':'+thrownError); } });
以jQuery實作AJAX為例,我們通常會以送出GET或POST請求的方式,帶上一些參數資料,再丟給一個負責處理的目標網址,而這個目標網址的PHP檔會接收我們傳過去的參數,之後再進行後端的各種處理,完成後端處理時,後端 PHP 也要回報結果給前端,前端如果成功收到結果,就會觸發 success 的 function;反之如果 Ajax 呼叫的過程中發生問題,則會觸發 error 的 function。
$.ajax 函式有非常多參數可設定,以下說明為求簡單換成 $.post,一樣都是 Ajax 呼叫,只是 $.post 預設就走 POST,可設定的參數和事件也比較少:
$.post( 'https://my_ajax_url.test/ajax.php', { arg: 'arg data' }, function(res) { console.log(res); // 後端回傳結果 } );
在WP實作AJAX的概述
在WP實作ajax的效果,大致也是採用這種方式,但是無論前台、後台中的任何一個頁面,都統一要將參數資料丟到 https://wp網址/wp-admin/admin-ajax.php 這個目標網址。當你把資料丟過去之後,你就可以在functions.php或者plugin裡利用hook function,去取得丟過來的參數資料。
請注意,本文以下的例子為求容易理解原理,因此沒有考慮最佳的實作方式,建議你應該在理解運作原理後多多參考其他更好的作法。
在前台佈景實作AJAX效果
為求方便講解,我們直接修改佈景檔中的 header.php (請先確定你的WP網站已有載入jQuery),在<head>裡加入:
<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 ajax 統一處理窗口 https://wp網址/wp-admin/admin-ajax.php 的完整網址;然後我們要自己取一個action的名稱,之所以叫action,就是表示這裡的名稱會對應到等會要寫的hook function的名稱。
接著在header.php下方<body>之後找地方加入:
<input type="text" value="mrmu" id="my_id"> <input type="button" class="btn_ajax" value="按我">
如此前端的配置就完成了,接著到 functions.php找地方加入:
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 ); // 將 ajaxurl 定義於前端頁面,讓 javascript 可以取得 PHP 定義的後端資料 wp_localize_script( 'my_ajax_script', 'my_ajax_obj', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) ); }
如此我們就可以在佈景目錄下的/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 . ', arg2: '. $arg2 . ', 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撈出所需的資料,再作輸出就打完收工了。
上述的程式碼只是方便說明,還有很多進步空間。比如我自己實際 coding 時,通常會用 $.ajax 的方式來傳值,dataType 通常指定 json 居多,如此後端 ajax function 在回傳結果時可以帶入自訂的狀態碼、資料、錯誤訊息等,能讓前端方便判斷 json 裡的資料再作進一步反應,例如:
public function ajax_action_stuff() { if (empty($_POST['arg'])) { $error = new WP_Error( 'arg_empty', 'Error: No data.', $this->plugin_name ); wp_send_json_error( $error ); // 回傳json格式的錯誤訊息 } $arg = sanitize_text_field($_POST['arg']); // 永遠不要相信前端使用者輸入的資料都是善意的 /* 拿到前端傳來的資料了,看你要在後端做什麼處理... */ // 處理完了,要通知前端處理結果... $return = array( 'message' => __( 'Success', $this->plugin_name ), 'data' => $arg ); wp_send_json_success( $return ); // 回傳json格式的成功訊息 // 就不用再執行 die() 了 }
標籤:網站設計
分類:JavaScript技巧, WordPress, 網站設計
本文作者是Audi Lu
1 則留言
[…] WordPress Ajax 實作:https://audilu.com/2012/06/12/wordpress-ajax-by-jquery/https://www.mxp.tw/6859/ […]