问题描述:
今天工作中遇到的关于php请求判断是否是ajax的一个bug问题
本文js框架:jquery
PHP判断ajax请求的原理
在发送ajax请求的时候,我们可以通过XMLHttpRequest这个对象,创建自定义的header头信息
就是在header一层判断是否是ajax请求,对应的php根据$_SERVER[\'HTTP_X_REQUESTED_WITH\']判断。
判断代码:
/** * 当前请求是否ajax请求 * * @access public * @return bool */ function isAjax() { return isset($_SERVER[\'HTTP_X_REQUESTED_WITH\']) && $_SERVER[\'HTTP_X_REQUESTED_WITH\'] == \'XMLHttpRequest\'; }
注意点
- 一般情况下$_SERVER[\'HTTP_X_REQUESTED_WITH\']默认是XMLHttpRequest
- $_SERVER[\'HTTP_X_REQUESTED_WITH\']也可以自定义创建的,使用
XMLHttpRequest.setRequestHeader(
name
,value
);
可以参考文章:http://www.skygq.com/2011/01/04/php-check-request-from-ajax-or-normal/
PHP判断AJAX请求时的一个bug
上面的都是正确的,但是前提是在同域的情况下。
如果是跨域的话这个,上面的isAjax就完全不正确了。
跨域同域的问题参考:《$.getjson遇到的几个问题》
我使用$.getJSON来实现跨域,但是检测是否是ajax一直是false,我在尝试$get(参看:$.get实现返回解析json数据以及jsonp跨域)之后无果的之后,考虑要使用万能的$ajax方法,我仔细的阅读了ajax的文档发现这句话:
如果指定了script或者jsonp类型,那么当从服务器接收到数据时,实际上是用了<script>标签而不是 XMLHttpRequest对象。这种情况下,$.ajax()不再返回一个XMLHttpRequest对象,并且也不会传递事件处理函数,比如 beforeSend。
j解释
ajax跨域只能指定jsonp格式的数据,这个是就不是XMLHttpRequest对象了,就算你自定义一个$_SERVER[\'HTTP_X_REQUESTED_WITH\']也是没有意义的
解决的办法:
针对跨域情况的getjson 或者ajax(jsonp)可以使用ACCEPT请求头部格式来判断
PHP端对应$_SERVER[\'HTTP_ACCEPT\']
jsonp的请求一般是:text/javascript, application/javascript, */*
json的请求:application/json, text/javascript, */*
一个简单的判断跨域条件下的ajax请求:
switch ($_SERVER[\'HTTP_ACCEPT\']){ case \'application/json, text/javascript, */*\': // JSON 格式 break; case \'text/javascript, application/javascript, */*\': // javascript 或 JSONP 格式 break; case \'text/html, */*\': // HTML 格式 break; case \'application/xml, text/xml, */*\': // XML 格式 break; }
注意:这个判断的前提是服务端没有强制使用header设置返回格式
原文链接:http://www.php10086.com/2012/09/1162.html
另外:
$.ajax({
type: ’POST’,
url: ’http://www.yourwebsite.com’,
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader(“request_type”,”ajax”);
},
data: ’test=test’,
success: function(rs) {
alert(‘ok’);
}
}
});
PHP代码: echo isset($_SERVER[\'HTTP_REQUEST_TYPE\']) && $_SERVER[\'HTTP_REQUEST_TYPE\'] == "ajax" ? "it is ajax" : "it is NOT ajax.";
还有一种方法,js里面不用加beforeSend里面的代码,直接在PHP里面作判断:
echo isset($_SERVER[\'HTTP_X_REQUESTED_WITH\']) && $_SERVER[\'HTTP_X_REQUESTED_WITH\'] ===\'XMLHttpRequest\' ?\'it is ajax\' : \'it is NOT ajax\';
PS:判断是否是Flash提交数据 echo isset($_SERVER[\'HTTP_USER_AGENT\']) && (stripos($_SERVER[\'HTTP_USER_AGENT\'],\'Shockwave\')!==false || stripos($_SERVER[\'HTTP_USER_AGENT\'],\'Flash\')!==false) ? echo \'it is flash data\':\'it is not flash data\';
原文:http://www.wei-blog.com/archives/619.html