PHP常用代码段

2016-05-17

总结日常使用的PHP代码片段

1.判断是否为手机号

<?php
function check_phone($phone){
    if(preg_match("/^1\d{10}$/",$phone)){
        return true;  //是手机号
    }
    return false;  //不是手机号
}

var_dump(check_phone('15350781443'));

输出:

bool(true)

说明:

“^1”表示以1开头

“\d”表示匹配一个数字字符。等价于 [0-9]。

“{10}”表示匹配10次

“$” 匹配输入字符串的结束位置

第二个数字通常是3456789这几个数字,那就可以更精确的去匹配:/^1[3456789]\d{9}$/

1.1.判断是否是电话或手机号

<?php
function check_phone_mobile($phone)
{
    if (preg_match("/^[0-9+][0-9]*-?[0-9]*[0-9]$/", $phone) && strlen($phone) < 16) {
        return true;  //是电话或手机号
    }
    return false;  //不是电话或手机号
}
var_dump(check_phone_mobile('0512-65896234'));
var_dump(check_phone_mobile('+8614526325986'));
var_dump(check_phone_mobile('x8614526325986'));

输出:

bool(true)
bool(true)
bool(false)

说明:

支持区号和+国际电话,字符长度16根据需要修改。

2.提取手机号

<?php
function get_phone($str){
    if (preg_match_all("/1[3456789]\d{9}/", $str, $phone)) {
        return $phone;
    }
    return false;
}

$str = '马路的手机是189123456786号码,小萌马的手机号是14659863526号码,hack member:17856985624,17625632659';

var_dump(get_phone($str));

输出:

array(1) {
  [0]=>
  array(4) {
    [0]=>
    string(11) "18912345678"
    [1]=>
    string(11) "14659863526"
    [2]=>
    string(11) "17856985624"
    [3]=>
    string(11) "17625632659"
  }
}

3.提取HTTP代理

<?php
function get_http_proxy($str){
    if (preg_match_all("/(\d+\.\d+\.\d+\.\d+)+[^0-9]+(\d+)/",$str,$proxy)) {
        return $proxy;
    }
    return false;
}

$str = '183.131.76.27	8888	浙江温州	高匿	HTTP	193天	不到1分钟
Cn	183.47.175.14	8888	广东广州	高匿	HTTP	18小时	不到1分钟
Cn	220.170.182.5	80	湖南株洲	高匿	HTTP	4天	不到1分钟';

var_dump(get_http_proxy($str));

输出:

array(3) {
  [0]=>
  array(3) {
    [0]=>
    string(18) "183.131.76.27	8888"
    [1]=>
    string(18) "183.47.175.14	8888"
    [2]=>
    string(16) "220.170.182.5	80"
  }
  [1]=>
  array(3) {
    [0]=>
    string(13) "183.131.76.27"
    [1]=>
    string(13) "183.47.175.14"
    [2]=>
    string(13) "220.170.182.5"
  }
  [2]=>
  array(3) {
    [0]=>
    string(4) "8888"
    [1]=>
    string(4) "8888"
    [2]=>
    string(2) "80"
  }
}

4.判断手机归属地 (淘宝接口)

<?php
function get_phone_address($phone){
    $str = file_get_contents('https://tcc.taobao.com/cc/json/mobile_tel_segment.htm?tel='.$phone);
    $str = iconv('GBK', 'UTF-8', $str);  //淘宝页面是GBK编码转UTF-8方便处理
    if(preg_match_all("/(\w+):'([^']+)/", $str, $m)) {
        return array_combine($m[1], $m[2]);
    }
    return false;  //没有匹配到
}

print_r(get_phone_address('17625632659'));

输出:

Array
(
    [mts] => 1762563
    [province] => 江苏
    [catName] => 中国联通
    [telString] => 17625632659
    [areaVid] => 30511
    [ispVid] => 137815084
    [carrier] => 江苏联通
)

5.判断邮箱地址是否正确

常见的可以用这种方式:

<?php
function check_email($email){
    if (filter_var($email, FILTER_VALIDATE_EMAIL)){
        return true;
    }else{
        return false;
    }
}

$email="xman@malu.me";
var_dump(check_email($email));

输出:

bool(true)

但这种方式并不严格,比如“xman%@malu.me”加上%特殊字符也能通过,所以我们以正则来精确匹配:

<?php
function check_email($email){
    if (preg_match('/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/',$email)){
        return true;
    }else{
        return false;
    }
}

$email="xman%@malu.com";
var_dump(check_email($email));

输出:

bool(false)

6.判断是否是URL

<?php
function check_url($URL){
    if (filter_var($URL, FILTER_VALIDATE_URL)) {
        return true;
    } else {
        return false;
    }
}

$URL = 'http://malu.me';
var_dump(check_url($URL));

输出:

bool(true)

以上用系统过滤器来检查,更多过滤参数参考官方文档:http://php.net/manual/en/filter.constants.php

7.二维数组去重

一维数组可以用系统函数array_unique(),二维数组如下:

<?php
$arr = array(
    array('id' => 1,'name' => 'aaa'),
    array('id' => 2,'name' => 'bbb'),
    array('id' => 3,'name' => 'ccc'),
    array('id' => 4,'name' => 'ddd'),
    array('id' => 5,'name' => 'ccc'),
    array('id' => 6,'name' => 'aaa'),
    array('id' => 7,'name' => 'bbb'),
);
function assoc_unique($arr, $key)
{
    $rAr=array();
    for($i=0;$i<count($arr);$i++)
    {
        if(!isset($rAr[$arr[$i][$key]]))
        {
            $rAr[$arr[$i][$key]]=$arr[$i];
        }
    }
    return array_values($rAr);
}
$arr = assoc_unique($arr,'name');
print_r($arr);

输出:

Array
(
    [0] => Array
        (
            [id] => 1
            [name] => aaa
        )
    [1] => Array
        (
            [id] => 2
            [name] => bbb
        )
    [2] => Array
        (
            [id] => 3
            [name] => ccc
        )
    [3] => Array
        (
            [id] => 4
            [name] => ddd
        )
)

8.获取客户端IP

<?php
function get_client_ip($type = 0)
{
	$type = $type ? 1 : 0;
	static $ip = NULL;
	if ($ip !== NULL) return $ip[$type];
	if (isset($_SERVER['HTTP_X_REAL_IP'])) {//nginx 代理模式下,获取客户端真实IP
		$ip = $_SERVER['HTTP_X_REAL_IP'];
	} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {//客户端的ip
		$ip = $_SERVER['HTTP_CLIENT_IP'];
	} elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {//浏览当前页面的用户计算机的网关
		$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
		$pos = array_search('unknown', $arr);
		if (false !== $pos) unset($arr[$pos]);
		$ip = trim($arr[0]);
	} elseif (isset($_SERVER['REMOTE_ADDR'])) {
		$ip = $_SERVER['REMOTE_ADDR'];//浏览当前页面的用户计算机的ip地址
	} else {
		$ip = $_SERVER['REMOTE_ADDR'];
	}
	// IP地址合法验证
	$long = sprintf("%u", ip2long($ip));
	$ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
	return $ip[$type];
}

echo get_client_ip();
echo "\n";
echo get_client_ip(1);

输出:

192.168.0.105
3232235625

其中$type为1时输出IP整形

9.获取HTTPS状态

<?php
function is_HTTPS(){
	if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 1){  //Apache
		return true;
	}elseif(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on'){ //IIS
		return true;
	}elseif(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'){  //nginx proxy
		return true;
	}elseif(isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443){ //其他
		return true;
	}
	return false;
}

var_dump(is_HTTPS());

输出:

bool(true)

返回true为HTTPS,false为HTTP

10.判断php版本是否高于某个版本

首先可以通过以下2种方法获取版本号:

phpversion();
PHP_VERSION;

使用version_compare函数判断:

<?php
if (version_compare(PHP_VERSION, '5.0.0', '>=')) {
    echo 'I am using PHP 5, my version: ' . PHP_VERSION . "\n";
}

11.生成机器识别难度较大的验证码

<?php
/*
 * 机器识别难度较大的验证码
 */
class VerifyCode
{
    
    //声明图像大小
    private $width = 100;
    private $height = 46;
    
    //验证码字符有限集
    private $v_char = '1234567890';
    private $v_code_str = '';
    
    //验证码数量
    private $v_num = 4;
    
    // 第i个文字x轴起始位置计算公式: x轴起始坐标 = margin + padding * i
    //文字内外边距
    private $padding = 18;
    private $margin = 6;
    
    //字体大小
    private $font_size = 30;
    
    //字体逆时针旋转的角度
    private $font_angles = array(-5, 5);
    
    //字体名称
    private $font = 'segoesc.ttf';
    
    //图像容器
    private $img;
    
    //颜色容器
    private $colors = array();
    
    
    /**
     * 生成图片验证码主逻辑
     */    
    public function __construct()
    {
        //生成一幅图像
        $this->img = imagecreate($this->width, $this->height);
        
        //生成颜色
        $r = mt_rand(100,150);
        $g = mt_rand(100,150);
        $b = mt_rand(100,150);

        $this->colors['col'] = imagecolorallocatealpha($this->img, $r,  $g,  $b,127);

        // 设置GD库环境变量 
        // putenv('GDFONTPATH=' . realpath('.'));
        
        //生成验证码字符
        $this->randomContent();
    }
    
    /**
     * 输出验证码,返回值是验证码的字符串表示
     */
    public function show()
    {
        $this->generate();
        
        header('Cache-Control: private, max-age=0, no-store, no-cache, must-revalidate');
        header('Cache-Control: post-check=0, pre-check=0', false);
        header('Pragma: no-cache');
        header("content-type: image/png");
        
        ImagePNG($this->img);
        ImageDestroy($this->img);
        
        return $this->v_code_str;
    }
     
    /**
     * 生成随机的验证码的内容
     */
    private function randomContent()
    {
        for($i = 0; $i < $this->v_num; $i++)
        {
            $this->v_code_str .= $this->v_char[ rand(0, strlen($this->v_char) - 1)];
        }
    }
    
    /**
     * 生成验证码的图像
     */
    private function generate()
    {    
        //生成验证码的算法
        for($i = 0; $i < $this->v_num; $i++)
        {
            // 下一个字符的起始x轴坐标
            $x = $this->margin + $this->padding * $i;    
            // 下一个字符的起始y轴坐标
            $y = 38;                     
            
            imagettftext(
                $this->img, 
                $this->font_size, 
                $this->font_angles[ rand(0, count($this->font_angles) - 1) ], 
                $x, $y, 
                $this->colors['col'], 
                $this->font,    //加上了字体的相对路径
                $this->v_code_str[ $i ]
            );
        }
        
        $dst = imagecreatetruecolor($this->width, $this->height);
        imagealphablending($dst, false);
        imagesavealpha($dst, true);
        $dWhite = imagecolorallocatealpha($dst, 0, 0, 0,127);
        imagefill($dst,0,0,$dWhite);
        
        //扭曲,变形
        for($i = 0; $i < $this->width; $i++) 
        {  
            // 根据正弦曲线计算上下波动的posY  
             
            $offset = 5; // 最大波动几个像素  
            $round = 2; // 扭2个周期,即4PI  
            $posY = round(sin($i * $round * 2 * M_PI / $this->width ) * $offset); // 根据正弦曲线,计算偏移量  
  
            imagecopy($dst, $this->img, $i, $posY, $i, 0, 1, $this->height);  
        } 
        
        $this->img = $dst;

        imagefilter($this->img,IMG_FILTER_BRIGHTNESS,0);
        // imagefilter($this->img,IMG_FILTER_GAUSSIAN_BLUR);

    }
    
    public function __destruct()
    {
        unset($this->colors);
    }
}

使用:

<?php
include_once('VerifyCode.class.php');
$vc = new VerifyCode();
$vc->show();

12.缩减html代码

function sanitize_output($buffer) {

    $search = array(
        '/\>[^\S ]+/s',     // strip whitespaces after tags, except space
        '/[^\S ]+\</s',     // strip whitespaces before tags, except space
        '/(\s)+/s',         // shorten multiple whitespace sequences
        '/<!--(.|\s)*?-->/' // Remove HTML comments
    );

    $replace = array(
        '>',
        '<',
        '\\1',
        ''
    );

    $buffer = preg_replace($search, $replace, $buffer);

    return $buffer;
}

使用:

$html_body = '
<html>

<head>
<title>一个 HTML 页面</title>
</head>

<body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>

</html>
';

echo sanitize_output($html_body);

输出:

<html><head><title>一个 HTML 页面</title></head><body><p>body 元素的内容会显示在浏览器中。</p><p>title 元素的内容会显示在浏览器的标题栏中。</p></body></html>

12.1缩减css和js

这是一款合并压缩css和js不错的库:https://github.com/mrclay/minify

13.正则提取日志

function get_log($str){
    $pattern = '/^\[(?P<time>[^\]]+)\] (?P<type>[^ ]+): (?P<info>[^ ]+) \["(?P<add>[^"]+)"\] (?P<json>[^ ]+)/i';
    preg_match($pattern, $str,$match);
    $res = array();
    $res['time'] = strtotime($match['time']);
    $res['type'] = $match['type'];
    $res['info'] = $match['info'];
    $res['add']  = $match['add'];
    $res['json'] = json_decode($match['json']);
    return $res;
}
$logLine = '[2019-04-25 17:04:22] security.INFO: 成功登录 ["江苏省苏州市"] {"url":"/login","ip":"1.9.12.75","http_method":"GET","server":"malu.me","referrer":null}';
var_dump(get_log($logLine));

输出:

array(5) {
    ["time"]=>
    string(19) "2019-04-25 17:04:22"
    ["type"]=>
    string(13) "security.INFO"
    ["info"]=>
    string(12) "成功登录"
    ["add"]=>
    string(18) "江苏省苏州市"
    ["json"]=>
    object(stdClass)#5 (5) {
        ["url"]=>
        string(6) "/login"
        ["ip"]=>
        string(9) "1.9.12.75"
        ["http_method"]=>
        string(3) "GET"
        ["server"]=>
        string(7) "malu.me"
        ["referrer"]=>
        NULL
    }
}