不太好的Ajax实现
可能有不少插件会这样来实现
require_once( "../../../../wp-config.php" ); // or require_once( "../../../../wp-load.php" );
这样做的坏处很多, 一旦用户设置的目录不同, 相对路径就会失效.并且, 如果你在你的插件中使用的是面向对象的写法, 你将无法直接使用一些变量和私有方法. 最大的坏处就是会导致整个Wordpress的框架额外重新加载一遍.
使用wp_localize_script()来声明javascript全局变量
这是一个伟大的函数:
wp_localize_script( $handle, $namespace, $variable_array );
比如我们这样来声明一个URL来处理Ajax请求:
// 插入发起AJAX请求的js文件 wp_enqueue_script( 'my-ajax-request', plugin_dir_url( __FILE__ ) . 'js/ajax.js', array( 'jquery' ) );
// 声明用来处理Ajax请求的URL, 这里我们使用 (wp-admin/admin-ajax.php)
wp_localize_script( 'my-ajax-request', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
这样的做法就没那么丑陋了…现在来看一看在标签中生成的html的话, 大概是这样的:
<script type="text/javascript" src="http://hongwei.im/wordpress/wp-content/plugins/myajax/js/ajax.js"></script> <script type="text/javascript"> /* <![CDATA[ */ var MyAjax = { ajaxurl: "http://hongwei.im/wordpress/wp-admin/admin-ajax.php" }; /* ]]> */ </script>
用admin-ajax.php来处理Ajax请求
Ajax请求应该被指向wp-admin/admin-ajax.php, 文件名中的”admin”可能会引起困惑, 但是不管是前台的还是后台的Ajax请求都是在admin-ajax.php处理的.
向admin-ajax.php发送请求的时候, 有一个必须的参数是action, 因为admin-ajax.php需要根据用户是否登陆了来触发不同的hooks
// 如果没登陆, 会触发这个hook do_action( 'wp_ajax_nopriv_' . $_REQUEST['action'] );
// 如果登陆了, 会触发这个hook do_action( 'wp_ajax_' . $_POST['action'] );
发出Ajax请求的代码大概如下:
jQuery.post( MyAjax.ajaxurl, { action : 'myajax-submit', postID : MyAjax.postID }, function( response ) { alert( response ); } );
现在, 我们只需要在我们的主题文件中处理一下Ajax请求, 并不需要在单独的文件中来处理
add_action( 'wp_ajax_nopriv_myajax-submit', 'myajax_submit' ); add_action( 'wp_ajax_myajax-submit', 'myajax_submit' ); function myajax_submit() { $postID = $_POST['postID']; $response = json_encode( array( 'success' => true ) ); header( "Content-Type: application/json" ); echo $response; // 这个很关键啊有木有: 别忘记 "exit" exit; }
使用nonces和权限控制
检查权限有的时候会很烦, 尤其是在你开发的过程中, 很费时费力, 但是权限控制确实很重要, 可以保证你的网站的安全. 在处理Ajax请求的时候, 你需要使用两重检验措施:
Nounces
Nonces是一组生成的数字并且只能被使用一次, Nonces可以用来确保Ajax请求来源的可靠性. 关于Nonces的含义, 这里有一篇有趣的解释Nonce – It’s like the deli counter, 这个例子很生动有木有…
When you arrive at a deli counter you’re asked to take a ticket. Once the counter reaches your number you had the ticket back to the server (who throws it away) and they serve you. They then move onto serving the next person in the who’s ticket matches the number of the digital screen.
If someone comes along and tries to jump the line (queue) they can’t unless they have a ticket.
If they manage to get hold of someones old ticket, they can’t use it, as it’s already been used and the digital counter has moved on.
To further extend the analogy, you then make every customer sign for the ticket when they take one, and you then check not only that there ticket matches but also make them sign again to check that their first signature matches the one they have before they get served.
Taking it to a silly level, you’d only allow users to get a ticket when they walked in the front door of the store (that they have to sign for). This then prevents someone climbing in a window and trying to forge your signature to get served. Because they didn’t come in the front door, they don’t have any access to the tickets, so they have no way of jumping ahead of you and ordering the last of the Bologna.
需要注意的是, 并不是所有时候都需要使用Nonces, 如果Ajax请求是来操作数据或者内容的, 那么你需要使用Nonces, 如果Ajax请求只是来读取一些数据, 那你很可能就不需要使用Nonces了.
如何使用呢? 首先要生成nonce, 然后在wp_localize_script()中把它设成一个javascript的变量:
wp_enqueue_script( 'my-ajax-request', plugin_dir_url( __FILE__ ) . 'js/ajax.js', array( 'jquery' ) ); wp_localize_script( 'my-ajax-request', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ), // 生成一个ID为 "myajax-post-comment-nonce" 的nonce 'postCommentNonce' => wp_create_nonce( 'myajax-post-comment-nonce' ), ) );
然后在Javascript代码就可以使用全局变量MyAjax.postCommentNonce来获取nonce了, 你需要把nonce跟Ajax请求一起发出去:
jQuery.post( MyAjax.ajaxurl, { action : 'myajax-submit', postID : MyAjax.postID, postCommentNonce : MyAjax.postCommentNonce }, function( response ) { alert( response ); } );
注意的是nonce是一次性的, 每次需要生成新的nonce, 旧的nonce在下次检测时会失败.
权限控制
直接上代码, 看看如何检查权限
add_action( 'wp_ajax_nopriv_myajax-submit', 'myajax_submit' ); add_action( 'wp_ajax_myajax-submit', 'myajax_submit' ); function myajax_submit() { $nonce = $_POST['postCommentNonce']; if ( ! wp_verify_nonce( $nonce, 'myajax-post-comment-nonce' ) ) die ( 'Busted!') if ( current_user_can( 'edit_posts' ) ) { $postID = $_POST['postID']; $response = json_encode( array( 'success' => true ) ); header( "Content-Type: application/json" ); echo $response; } exit; }
使用WordPress内置的jQuery Form plugin来提交表单
大概有的人还不知道, WordPress提供了一个jQuery插件来实现表单的Ajax提交, 那就是jquery-form
如何加载就不说, 请看另一篇
jQuery('#myForm1').ajaxForm({ data: { //数据 }, dataType: 'json', beforeSubmit: function(formData, jqForm, options) { //发送前对数据进行处理 }, success : function(responseText, statusText, xhr, $form) { //请求成功后的处理 } });