PHP根据HTTP_USER_AGENT判断客户端访问是否为手机访问

 更新时间:2016年11月25日 15:41  点击:1911
现在web发展速度非常快.各种响应式的站点越来越多.除了APP外.在平时可能需要根据客户终端访问来加载不同时模板或跳转到不同时的域名下.现在分享一个函数.可以做到这样判断.android、ios和wp都已经测试过.
 代码如下 复制代码

 

//判断moblie
function is_mobile()
{
    $_SERVER['ALL_HTTP'] = isset($_SERVER['ALL_HTTP']) ? $_SERVER['ALL_HTTP'] : '';
 
    $mobile_browser = '0';
 
    if(preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|iphone|ipad|ipod|android|xoom|ios)/i', strtolower($_SERVER['HTTP_USER_AGENT'])))
        $mobile_browser++;
 
    if((isset($_SERVER['HTTP_ACCEPT'])) and (strpos(strtolower($_SERVER['HTTP_ACCEPT']),'application/vnd.wap.xhtml+xml') !== false))
        $mobile_browser++;
 
    if(isset($_SERVER['HTTP_X_WAP_PROFILE']))
        $mobile_browser++;
 
    if(isset($_SERVER['HTTP_PROFILE']))
        $mobile_browser++;
 
    $mobile_ua = strtolower(substr($_SERVER['HTTP_USER_AGENT'],0,4));
    $mobile_agents = array(
                        'w3c ','acs-','alav','alca','amoi','audi','avan','benq','bird','blac',
                        'blaz','brew','cell','cldc','cmd-','dang','doco','eric','hipt','inno',
                        'ipaq','java','jigs','kddi','keji','leno','lg-c','lg-d','lg-g','lge-',
                        'maui','maxo','midp','mits','mmef','mobi','mot-','moto','mwbp','nec-',
                        'newt','noki','oper','palm','pana','pant','phil','play','port','prox',
                        'qwap','sage','sams','sany','sch-','sec-','send','seri','sgh-','shar',
                        'sie-','siem','smal','smar','sony','sph-','symb','t-mo','teli','tim-',
                        'tosh','tsm-','upg1','upsi','vk-v','voda','wap-','wapa','wapi','wapp',
                        'wapr','webc','winw','winw','xda','xda-'
                        );
 
    if(in_array($mobile_ua, $mobile_agents))
        $mobile_browser++;
 
    if(strpos(strtolower($_SERVER['ALL_HTTP']), 'operamini') !== false)
        $mobile_browser++;
       www.111cn.net
    // Pre-final check to reset everything if the user is on Windows
    if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows') !== false)
        $mobile_browser=0;
 
    // But WP7 is also Windows, with a slightly different characteristic
    if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'windows phone') !== false)
        $mobile_browser++;
 
    if($mobile_browser>0)
        return true;
    else
        return false;
}

在php学习中error_reporting和display_errors是两个非常重要的参数,我们在学习调试过程中是少不了它们的,开启与关闭这两个错误日志非常的简单只要在php.ini简单处理即可,下文会有介绍。

我们知道产品的生产环境肯定是不给予显示错误的,于是:
php.ini中将 display_errors = Off 改为display_errors = On
或者 ini_set('display_errors',0);

其次,我们知道php的错误级别是由error_reporting【error_reporting详细教程】控制的,但是有很多人在生产环境关闭了错误信息提示
error_reporting(0);

其实这种做法,我觉得不科学,在codeigniter框架就是这样

 代码如下 复制代码

if (defined('ENVIRONMENT'))
{
 switch (ENVIRONMENT)
 {
  case 'development':
   error_reporting(E_ALL);
  break;
 
  case 'testing':
  case 'production':
   error_reporting(0);
  break;
 
  default:
   exit('The application environment is not set correctly.');
 }
}

线上的错误信息肯定是要记录的,error_reporting(0)这样会导致所有的错误信息不会记录,应该:error_reporting = E_ALL & ~E_NOTICE,只要display_errors = Off,错误信息就不会再页面上显示,因为display_errors的优先级别更高。

特别要注意的是:
如果php.ini中log_errors= On,据官方的说法,那么必须指定error_log文件,如果没指定或者指定的文件没有权限写入,那么照样会输出到正常的输出渠道,那么也就使得display_errors 这个指定的Off失效,错误信息还是打印了出来。将log_errors = Off就行了。

总结下,在生产环境中不现实错误信息还能记录错误日志:

 

 代码如下 复制代码
<?php
/**
 * 记录生产环境错误日志
 *
 * @link http://www.111cn.net
 */
error_reporting(E_ALL);
ini_set('display_errors',0);
ini_set('log_errors',1);
ini_set('error_log','E:\'.date('Y-m-d').'_phpddt.com.txt');
有很多的cms都有分词的功能,多数都是用于tag标签中,本人自己写了一个分词的方式,没有强大的词库,在网上下载了一个词库和一个分词的代码

将词库和代码结合加以调试实现了中文分词..功能不是很强大高手不喜勿喷....。将实现后的代码分享给大家

 代码如下 复制代码

<?php
function get_keywords_str($content='')
{
require('./phpanalysis.class.php');
$pa = new PhpAnalysis('utf-8', 'utf-8', false);
$pa->LoadDict();//载入
$pa->SetSource($content);//将要分开的内容传入
$pa->StartAnalysis(false);
$tags = $pa->GetFinallyResult(',',6);//分词样式是以逗号分开/分词长度
return $tags; www.111cn.net
}
$str="李世民是唐朝的第二任皇帝";
echo "分词前:".$str."<br/>";
echo "分词后:".get_keywords_str($str);
?>

全部分词源码下载地址:http://www.111cn.net//demo/fenci.rar

下面来给各位朋友推荐一个非常不错基于php curl函数进行的数据post例子,希望此例子对各位朋友会有所帮助。
 代码如下 复制代码

////二纬码 
$QRCode_URL="https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=".$ACC_TOKEN; 
 
$data ='{"expire_seconds": 1800, "action_name": "QR_SCENE", "action_info": {"scene": {"scene_id": 123}}} '; 
/*
$ch = curl_init($MENU_URL);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json','Content-Length:'.strlen($data)));
$info = curl_exec($ch);
*/ 
function post($url, $params = false, $header = array()){ 
$ch = curl_init(); 
$cookieFile = 'sdadsd_cookiejar.txt'; 
 
curl_setopt($ch, CURLOPT_POST, 1); 
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 60); 
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieFile); 
curl_setopt($ch, CURLOPT_COOKIEFILE,$cookieFile); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,FALSE); 
curl_setopt($ch, CURLOPT_HTTPGET, true); 
curl_setopt($ch, CURLOPT_TIMEOUT, 30); 
if($params !== false){ curl_setopt($ch, CURLOPT_POSTFIELDS , $params);} 
curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 5.1; rv:21.0) Gecko/20100101 Firefox/21.0'); 
curl_setopt($ch, CURLOPT_URL,$url); 
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 
  www.111cn.net
$result = curl_exec($ch); 
curl_close($ch); 
 
return $result; 

$result = post($QRCode_URL,$data); 
urlencode与rawurlencode函数是对url进行一些处理,但在处理时它们是有区别的,特别是对于些特殊字符时它们表现出来的是完全不一样的,下面我就来详细举例子来说明一下这两个url处理函数吧。

前段时间说自己遇到了个《URL加号引发错误》的BUG,引起这个bug的原因就是自己在URL中使用了 urlencode 函数,该函数会把空格转换成加号,这样就导致URL解析出错,而空格只有转换成 %20 才可以可以正常解析,这时我们就需要使用 rawurlencode 函数。下面就介绍一下 urlencode 函数与 rawurlencode 函数的区别:

urlencode 函数:

返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数,空格则编码为加号(+)。此编码与 WWW 表单 POST 数据的编码方式是一样的,同时与 application/x-www-form-urlencoded 的媒体类型编码方式一样。由于历史原因,此编码在将空格编码为加号(+)方面与 RFC1738 编码(参见 rawurlencode())不同。

rawurlencode 函数:

返回字符串,此字符串中除了 -_. 之外的所有非字母数字字符都将被替换成百分号(%)后跟两位十六进制数。这是在 » RFC 3986 中描述的编码,是为了保护原义字符以免其被解释为特殊的 URL 定界符,同时保护 URL 格式以免其被传输媒体(像一些邮件系统)使用字符转换时弄乱。下面我们来看一下例子:

 代码如下 复制代码

<?php

$string = "hello world";

echo urlencode($string) . '<br/>'; //输出:hello+world
echo rawurldecode($string) . '<br/>';//输出:hello%20world

?>

具体例子比较:

 代码如下 复制代码

<?php
for ($i = 0x20; $i < 0x7f; $i++) {
$str .= dechex($i);
}

$asscii = pack("H*",$str);
echo "所有的可打印的asscii字符:(从空格到~)n". $asscii."\n";
echo "urlencode 的结果:\n".urlencode($asscii);
echo "\n";
echo "urlencode 不做编码的字符:\n".preg_replace("/%.{2}/","",urlencode($asscii));
echo "\n";
echo "rawurlencode 的结果:\n".rawurlencode($asscii);
echo "\n";
echo "rawurlencode 不做编码的字符:\n".preg_replace("/%.{2}/","",rawurlencode($asscii));
echo  "\n";

exit;
?>

输出结果:
———————————————————————————
所有的可打印的asscii字符:(从空格到~)
!"#$%&’()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz{|}~
urlencode 的结果:
+%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E
urlencode 不做编码的字符:
+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz
rawurlencode 的结果:
%20%21%22%23%24%25%26%27%28%29%2A%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E
rawurlencode 不做编码的字符:
-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz

---------------------------------------------------------------------------------
比较二者的结果:
1.  数字、大小写字母都不编码
2.  减号、点号、下划线  三个不编码
3. rawurlencode比urlencode多编码一个”加号“

关于JavaScript中escape与encodeURIComponent的区别:

 代码如下 复制代码

>>>  console.log(encodeURIComponent("统一注册1"));

%E7%BB%9F%E4%B8%80%E6%B3%A8%E5%86%8C1
>>> console.log(escape("统一注册1"));
%u7EDF%u4E00%u6CE8%u518C1

<?php
echo iconv("utf-8","gbk",urldecode("%E7%BB%9F%E4%B8%80%E6%B3%A8%E5%86%8C1"));
echo "\n";
echo urldecode("%u7EDF%u4E00%u6CE8%u518C1");
// 使用下面的unescape可以
//echo iconv("utf-8","gbk",unescape("%u7EDF%u4E00%u6CE8%u518C1");
exit;
?>

输出结果:
======================================
统一注册1
%u7EDF%u4E00%u6CE8%u518C1
======================================

结果说明:
1. encodeURIComponent 总是把输入转换成utf8编码处理的,按字节编码
2. escape是按照unicode编码处理的,因为它也对url中不安全的字符做了编码,所以也可以在url中做编码使用,但是,服务器端不会自动解码,下面提供一个PHP版的解码函数,是用手册里找的:

<?php

 代码如下 复制代码

function unescape($str) {
    $str = rawurldecode($str);
    preg_match_all("/(?:%u.{4})|&#x.{4};|&#d+;|.+/U",$str,$r);
    $ar = $r[0];
    foreach($ar as $k=>$v) {
        if(substr($v,0,2) == "%u")
            $ar[$k] = iconv("UCS-2","UTF-8",pack("H4",substr($v,-4)));
        elseif(substr($v,0,3) == "&#x")
            $ar[$k] = iconv("UCS-2","UTF-8",pack("H4",substr($v,3,-1)));
        elseif(substr($v,0,2) == "&#") {
            $ar[$k] = iconv("UCS-2","UTF-8",pack("n",substr($v,2,-1)));
        }
    }
    return join("",$ar);
}

?>

 

>>> console.log(escape(" !\"#$%&'()*+,-./0123456789:;=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz{|}~"));
%20%21%22%23%24%25%26%27%28%29*+%2C-./0123456789%3A%3B%3C%3D%3E%3F@ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D%7E
>>> console.log(encodeURIComponent("!\"#$%&’()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz{|}~"));
%20!%22%23%24%25%26'()*%2B%2C-.%2F0123456789%3A%3B%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5D%5E_%60abcdefghijklmnopqrstuvwxyz%7B%7C%7D~
>>> console.log(escape("!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_abcdefghijklmnopqrstuvwxyz{|}~").replace(/%.{2}/g,""));

*+-./0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz
>>> console.log(encodeURIComponent("!\"#$%&’()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~").replace(/%.{2}/g,""));
!’()*-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~

结果比较:
escape未编码的字符: *+-./@_   共7个
encodeURIComponent未编码的字符: !’()*-._~  共9个

[!--infotagslink--]

相关文章