Sử dụng Ajax trong wordpress

Vì sao và khi nào thì sử dụng Ajax

Ajax rất hay, nó giúp chúng ta có thể load dữ liệu mà không cần tải lại trang web. Nhờ đó mà có thể tăng tốc website, tiện dụng cho người dùng hơn rất nhiều. Vì vậy sử dụng ajax vào đúng chỗ sẽ giúp load trang nhanh hơn.

Khi nào dùng ajax? Khi bạn muốn thực hiện 1 hành động gì đó mà không muốn tải lại trang web thì sử dụng Ajax

Cái nhìn khái quát

Vậy luồng của ajax trong wordpress như nào?

Từ Jquery (Ajax) truyền tham số vào xử lý thông qua wp_ajax_ và wp_ajax_nopriv_. Sau đó bên PHP xử lý xong sẽ trả kết quả về lại Js và từ đó mình sẽ thực hiện hành động dựa trên kết quả trả về
 

Thực thi Ajax trong wordpress

Ví dụ chúng ta tạo link cho phép người dùng vote bài viết, nếu user bật sử dụng javascript, liên kết sẽ sử lý dữ liệu động ajax, còn không hiển thị liên kết trang thông thường. Bạn có thể đặt link votes gần tiêu đề bài viết trong file single.php, thêm dòng code sau trong vòng lặp:

1
2
3
4
5
6
7
8
9
10
11
<?php
   $votes = get_post_meta($post->ID, "votes", true)
   $votes = ($votes == "") ? 0 : $votes;
?>
This post has <div id='vote_counter'><?php echo $votes ?></div> votes<br>
 
<?php
   $nonce = wp_create_nonce("my_user_vote_nonce");
    $link = admin_url('admin-ajax.php?action=my_user_vote&post_id='.$post->ID.'&nonce='.$nonce);
    echo '<a class="user_vote" data-nonce="' . $nonce . '" data-post_id="' . $post->ID . '" href="' . $link . '">vote for this article</a>';
?>

Lưu dữ liệu ‘votes’ gắn vào meta key của post. Meta field ‘votes’ sẽ lưu tổng số votes người dùng bình chọn cho bài viết. Nếu giá trị này chưa có bạn hiển thị chuỗi ban đầu bằng 0.

Chúng ta tạo link thông thường với thẻ A, chứa liên kết vào file admin-ajax.php trong đó xác định thông tin ‘action’ thực thi và các tham số sử dụng cho action như chỉ số post_id. Ở đây thiết lập chút bảo mật với tham số ‘nonce’ là chuỗi mã hóa nhận dạng giữa nơi gọi và nơi nhận cho sự kiện này, tránh hacker lợi dụng.

Để khởi tạo javascript cho liên kết votes, chúng ta thêm class ‘user_vote’ sẽ dùng để tạo sự kiện và thuộc tính data-post_id chứa ID của post. Những thuộc tính này sẽ tiện lấy bởi code javascript.

Sử lý action không có Javascript

Nếu bạn click vào link ngay bây giờ, bạn sẽ được chuyển đến trang admin-ajax.php và nội dung script trả về chuỗi 0. Tùy thuộc vào phiên bản wordpress, có thể trả về -1. Điều này nghĩa là không có hàm action được tìm thấy hoặc sử dụng hàm wordpress trong action bất hợp lệ, vd: gọi update_post_meta với anonymous. Trong plugin/theme của bạn tạo hàm thực thi action và gắn vào hook với tên action ‘my_user_vote’ trên địa chỉ URL bởi tham số action.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
add_action("wp_ajax_my_user_vote", "my_user_vote");
add_action("wp_ajax_nopriv_my_user_vote", "my_must_login");
 
function my_user_vote() {
 
   if ( !wp_verify_nonce( $_REQUEST['nonce'], "my_user_vote_nonce")) {
      exit("No naughty business please");
   }  
 
   $vote_count = get_post_meta($_REQUEST["post_id"], "votes", true);
   $vote_count = ($vote_count == '') ? 0 : $vote_count;
   $new_vote_count = $vote_count + 1;
 
   $vote = update_post_meta($_REQUEST["post_id"], "votes", $new_vote_count);
 
   if($vote === false) {
      $result['type'] = "error";
      $result['vote_count'] = $vote_count;
   }
   else {
      $result['type'] = "success";
      $result['vote_count'] = $new_vote_count;
   }
 
   if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
      $result = json_encode($result);
      echo $result;
   }
   else {
      header("Location: ".$_SERVER["HTTP_REFERER"]);
   }
 
   die();
 
}
 
function my_must_login() {
   echo "You must log in to vote";
   die();
}

Như đã giải thích ở trên, hook ‘wp_ajax_nopriv’ sẽ thực thi trước hook ‘wp_ajax’ và kích hoạt khi user chưa đăng nhập để hiển thị thông báo và có thể dừng sử lý hook wp_ajax tiếp sau đó bởi lệnh die().

Mặc định mọi ajax thông qua admin-ajax.php đều yêu cầu phiên làm việc người dùng, cái tên ‘admin’ cũng nói lên điều đó, nếu bạn không khai báo thêm hook ‘wp_ajax_nopriv_xxx’ thì sử dụng mặc định và bạn có thể thêm hook này liên kết vào hàm hiển thị dòng tin nhắn yêu cầu đăng nhập như ở đoạn code trên.

Để tiếp tục sử lý vào hook ajax ‘wp_ajax_’, bạn cần bỏ lệnh ngắt die() hoặc exit() trong action ‘wp_ajax_nopriv_’ và để tiết kiệm function cách tốt nhất là bạn trỏ 2 hook này vào chung hàm sử lý nội dung. Để hàm my_user_vote hoạt động cho mọi người dùng bạn sửa lại 2 hook trên như sau:

1
2
add_action("wp_ajax_my_user_vote", "my_user_vote");
add_action("wp_ajax_nopriv_my_user_vote", "my_user_vote");

Chúng ta xác nhận chuỗi nonce để đảm bảo nơi gửi là đúng, vì chuỗi này đều tạo ở nơi gửi và nơi nhận. Nếu không đúng có thể lời gọi từ hacker và chúng ta cho dừng script. Sử dụng hàm get_post_meta lấy lượng votes hiện tại và cập nhật +1 votes bởi hàm update_post_meta vào meta key ‘votes’.

Cuối cùng, chúng ta kiểm tra lời gọi URL xuất phát trực tiếp trên trình duyệt hay gọi ẩn bằng đường ajax sử dụng biến $_SERVER['HTTP_X_REQUESTED_WITH']. Nếu đúng vậy, bạn xuất chuỗi đối tượng JSON ra màn hình tạo với hàm json_encode. Hàm này sẽ được chuyển đổi sang mảng trong javascript, nơi nhận giá trị trả về.

Kết thúc script, bạn luôn nhớ để lệnh dừng die(). Nếu bạn không thêm lệnh này, bạn luôn nhận giá trị trả về 0/-1 kèm theo kết quả.

Thêm code Javascript sử lý Ajax

Chúng ta chèn thêm thư viện jQuery, vào trang và đảm bảo dependency này thêm trước đoạn code thực thi lệnh javascript mà bạn sẽ tạo hàm ajax vào link votes cho các posts.
Thêm các dòng sau đây vào functions.php

1
2
3
4
5
6
7
8
9
10
11
12
add_action( 'init', 'my_script_enqueuer' );
 
function my_script_enqueuer() {
   wp_register_script( "my_voter_script", WP_PLUGIN_URL.'/my_plugin/my_voter_script.js', array('jquery') );
    
   wp_enqueue_script( 'my_voter_script_obj', WP_PLUGIN_URL.'/my_plugin/empty_test.js' );
   wp_localize_script( 'my_voter_script_obj', 'myAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' )));       
 
   wp_enqueue_script( 'jquery' );
   wp_enqueue_script( 'my_voter_script' );
 
}

Bạn có thể khai báo lệnh thêm jquery vào thẻ head sau cũng đc tùy ý, vì hàm đăng ký script wp_register_script có khai báo các dependencies cần nạp trước rồi.
Hàm wp_localize_script có thể không cần thiết, nhưng là cách tốt để giúp bạn chuyển mảng php sang mảng biến javascript, rất hữu ích khi bạn viết javascript sang một file mới có lấy biến là giá trị từ PHP. Như vậy Code trên có tạo biến myAjax.ajaxurl chứa URL tới file admin-ajax.php.
Lưu ý: Để wp_localize_script có thể hoạt động, bạn cần chèn file script .js rỗng với tên khai báo vào wp_enqueue_script trùng với tên bạn sẽ gắn đối tượng javascript bởi wp_localize_script, giống như trên là ‘my_voter_script_obj’. Nếu file empty_test.js có nội dung có thể hàm ‘wp_localize_script’ sẽ không tạo đối tượng thành công.

Tạo file my_voter_script.js với nội dung sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
jQuery(document).ready( function() {
 
   jQuery(".user_vote").click( function() {
      post_id = jQuery(this).attr("data-post_id")
      nonce = jQuery(this).attr("data-nonce")
 
      jQuery.ajax({
         type : "post",
         dataType : "json",
         url : myAjax.ajaxurl,
         data : {action: "my_user_vote", post_id : post_id, nonce: nonce},
         success: function(response) {
            if(response.type == "success") {
               jQuery("#vote_counter").html(response.vote_count)
            }
            else {
               alert("Your vote could not be added")
            }
         }
      })  
 
   })
 
});

back top