PHP 开发笔记

如果你有任何问题或疑问,请发送Email至zrg1390556487@gmail.com!

1. PHP 常用操作

1.1. 基础入门

1.1.1. PHP vs Java vs C

  1. C/C++,编译成机器语言(二进制)来运行
  2. Java 编译成.class文件,称为 bytecode,由 jvm 来运行,Java 语言不垮平台,是 JVM 跨平台。
  3. 严格说,PHP是一门编译语言,由 zend 虚拟机编译成 opcode,在执行 opcode
  4. Opcode 能缓存吗?

    答:PHP本身不支持,但是 apc,xcache 等加速器实现了。
    
  5. PHP 是弱类型语言。C、Java是强类型语言

1.1.2. echo & print & printf & sprintf & var_dump & print_r

  1. echo

    输出函数,是命令,不能返回值。echo后面可以跟很多个参数,之间用分号隔开。
    echo比print稍快,因为它不返回任何值
    
  2. print

    是函数,可以返回一个值,只能有一个参数。
    
  3. printf

    把文字格式化以后输出,如:
    $name="hunte";
    $age=25;
    printf("my name is %s, age %d", $name, $age);
    
  4. sprintf

    跟printf相似,但不打印,而是返回格式化后的文字,其他的与printf一样。
    

1.1.3. 单引号和双引号的区别

单引号不支持变量的解析和转义字符,而双引号可以直接解析变量和转义字符!

1.1.4. isset vs empty vs is_null

  1. empty

    判断一个变量是否为空
    null、false、00、0、’0′、』。都会返回true。
    
  2. isset

    判断一个变量是否设置
    0、00、’0′、』、’ ‘、false、’false’、’null’都返回true。 
    只有值為null的变量返回true
    
  3. if 判断式

    0、00、0.0、’0′、』、false、null返回false 
    ‘00′、’0.0′、’null’、’false’、’ ‘返回true
    
  4. is_null 判断变量是否为NULL

    is_null,我们可以把它看成是!isset,是isset的一个逆操作,下面一张表可以很清楚的说明他们之间的关系:
    
    Table 1: empty vs isset vs is_null
    变量 empty is_null isset
    $a="" true false true
    $a=null true true false
    var $a true true false
    $a=array() true false true
    $a=false true false true
    $a=15 false false true
    $a=1 false false true
    $a=0 true false true
    $a="0" true false true
    $a="true" false false true
    $a="false" false false true

    总结

    • 只要变量是否为” “或者0,或者是 false 和 null,只要是这些值 empty 都会返回 true
    • isset是判断变量是否存在,只要你这个变量不是null或未赋值,返回结果都是true
    • is_null正好是isset的反结果

1.1.5. exit vs die

  1. die()是exit()函数的别名。功能上,die() 就等同于 exit();
  2. 使用场景:

    当传递给exit和die函数的值为0时,意味着提前终止脚本的执行,通常用exit()
    当程序出错时,可以给它传递一个字符串,它会原样输出在系统终端上,通常使用die()
    

1.1.6. include vs require vs include_once vs require_once

  • require will produce a fatal error (E_COMPILE_ERROR) and stop the script(致命错误)
  • include will only produce a warning (E_WARNING) and the script will continue(警告)

1.1.7. stripslashes, htmlspecialchars, htmlentities, and strip_tags

  1. stripslashes——Un-quotes a quoted string

    清理字符串中的反斜杠 \
    与之相反的是 addslashes,在字符串中的单引号('),双引号("),反斜杠(\),NULL前面添加反斜杠。通常默认的,php会对所有的GET,POST和COOKIE数据自动运行addslashes()
    
  2. htmlspecialchars——Convert special characters to HTML entities
  3. htmlentities——Convert all applicable characters to HTML entities
  4. strip_tags——Strip HTML and PHP tags from a string
  5. Strip 去除的意思

1.1.8. return, break, and continue

  1. return,立即停止执行函数内部的代码,然后继续执行下面的代码
  2. break,立即停止执行本循环体内的所有循环,最常见的switch循环。
  3. continue与break都是用于终止循环执行,所不同的是,break是彻底终止循环体的执行,而continue是结束本次循环,继续下一次的循环。

1.1.9. 值传递和引用传递的区别

/**
 * 值传递
 * @param [type]
 */
function add($a){
    $a++;
    $res = $a;
    return $res;
}
$a = 100;
echo $a.'<br />';   // 100
echo add($a).'<br />';  // 101
echo $a.'<br />';   // 100


/**
 * 引用传递
 * @param [type]
 */
function add(&$a){
    $a++;
    $res = $a;
    return $res;
}
$a = 100;
echo $a.'<br />';   // 100
echo add($a).'<br />';  // 101
echo $a.'<br />';   // 101


// 对象的引用
class A{
    var $abc="ABC";
}
$b =new A();
$c =$b; // 等效于 $c=&$b;
echo $b->abc;//这里输出ABC
echo "<br />";
echo $c->abc="DEF";//这里输出ABC $b->abc="DEF";
echo "<br />";
echo $c->abc;//这里输出 DEF
$d1 = clone $c;
echo "<br />";
echo $d1->abc="GHI"; //这里输出 GHI $d1->abc="GHI";
echo "<br />";
echo $d1->abc;//这里输出 GHI
echo "<br />";
echo $c->abc;//这里输出 DEF

// 函数的引用
function &test2(){
    static $b=0;//申明一个静态变量
    $b=$b+1;
    echo $b;
    return $b;
}
$a=test2();//这条语句会输出 $b的值 为1
echo "<br />";
$a=5;
$a=test2();//这条语句会输出 $b的值 为2
echo "<br />";
$a=&test2();//这条语句会输出 $b的值 为3。将return $b 中的 $b 变量的内存地址与 $a 变量的内存地址指向了同一个地方。
echo "<br />";
$a=5;
$a=test2();//这条语句会输出 $b的值 为6

// 函数地址引用
function test1(&$a){
    $a=$a+100;
}
$b=1;
test1($b);
echo $b;//输出101
//这里$b传递给函数的其实是$b的内存地址,通过在函数里改变$a的值,就可以改变$b的值
// 变量
$a="ABC";
$b =&$a;
echo $a;//这里输出:ABC
echo "<br />";
echo $b;//这里输出:ABC
$b="EFG";
echo "<br />";
echo $a;//这里$a的值变为EFG 所以输出EFG echo $b;//这里输出EFG
?>

1.1.10. 构造函数 vs 析构函数

  1. 构造函数
    • 类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
    • Java、C++ 构造函数的名称与类的名称是完全相同的,PHP 语言目前普遍用法是使用 __construct() 代替。
    • 构造函数不会返回任何类型,也不会返回 void。
  2. 析构函数
    • 类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。
    • Java、C++ 析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。PHP 语言普遍用法是使用 __desctruct() 代替。
    • 析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
    • 试图在析构函数(在脚本终止时被调用)中抛出一个异常会导致致命错误。

1.1.11. public, protected, private and final

  1. public 用于声明可以外部调用类或方法
  2. protected 声明只能被继承子类调用
  3. private 用于定义私有属性或方法,仅供内部类调用
  4. final 指定某个类不允许被继承或者是某个方法不允许被修改

1.1.12. PHP 命令传参

// 1. 使用 $argc $argv 接受参数
echo "接收到{$argc}个参数";
print_r($argv);

// 2. 使用getopt函数
$param_arr = getopt('name:age:');//只接受name和age两个参数
print_r($param_arr);
// $ php test.php -name john

// 3. 通过 php 系统定义 CLI 的常量:STDIN , STDOUT , STDERR
$fs = true;
$username = '';
do {
    if ($fs) {
    fwrite(STDOUT, '请输入用户名:');
    $fs = false;
    } else {
    fwrite(STDOUT, '抱歉,用户名不能为空,请重新输入:');
    }
    $username = trim(fgets(STDIN));
} while (!$username);
echo '您输入的用户名是:' . $username . "\r\n";

1.2. 字符串操作

1.2.1. 字符串大小写切换以及翻转和加密

//将小写字母全部变成大写字母
$a = 'hello world';
echo strtoupper($a);//HELLO WORLD!
//将大写字母全部变成小写字母
$b = 'HELLO WORLD!';
echo strtolower($b);//hello world!
//将语句中的首字母变成大写
$c = 'my name is fxxy';
echo ucfirst($c);//My name is fxxy
//将语句中每个字母的首字母变成大写
$d = 'my name is fxxy';
echo ucwords($d);//My Name Is Fxxy;

/字符串翻转函数
$e = 'hello world';
echo strrev($a);//!dlrow olleh 
//字符串加密函数
$f = 'hello fxxy';
echo md5($f);   //b9facffba44a838e493d2f8f28bb3584

1.2.2. 字符串截取

// 1. 按照字符所在索引进行截取:
$str = 'hello word,my name is fxxy';
echo substr($str,11);//my name is fxxy
echo substr($str,11,2);//my

// 2. 按照指定字符进行截取:
$str = 'hello world,my name is fxxy';
//截取某个字符在字符串中首次出现直到最后的所有字符(从左到右)
echo strchr($str,'my');//my name is fxxy
//另外一种写法
echo strstr($str,'my');//my name is fxxy
//不区分大小写的写法
echo stristr($str,'MY');//my name is fxxy
//截取某个字符在字符串中最后出现到最后的所有字符(从右到左)
echo strrchr($str,'o');//orld,my name is fxxy
//输出某个字符在字符串中首次出现的位置索引
echo strpos($str,'my');//12
//将字符串拆分成数组
$arry = explode(',',$str);
var_dump($arry);

// 在一个语句中,找出某个字出现了多少次,分别出现在哪个位置?
$str = 'hello world,my name is fxxy';
$num=0;
echo '字母【o】出现了位置索引是:';
for($i=0; strpos($str,'o',$i)!=0; $i=strpos($str,'o',$i)+1){
    $num+=1;
    echo strpos($str,'o',$i).'、';//4  7
}
echo '字母【o】总共出现了'.$num.'次';//2

// 3. 通过指定字符将主字符串进行拆分:
$arr = array();
$a = 'hello,world,my,name,is,fxxy';
$b = strtok($a,',');
while($b){
    $arr[] = $b;
    //array_push($arr,$b);
    $b = strtok(',');
}
echo "<pre>";var_dump($arr);exit;

// 4. 把查询字符解析到变量中:
$url = 'http://www.baidu.com?username=fxxy&age=24';
$msg = substr($url,(strpos($url,'?')+1));
parse_str($msg);
echo $username;
echo $age;

// 5. 将字符串每隔n个字符就拆分一次,并插入特定的分隔符:
$a = 'abcdefghijklmnopqrstuvwxyz';
echo chunk_split($a,5,' | ');

1.2.3. 字符串替换和比较函数

// 1. PHP字符串替换函数:
$str = 'hello world!';
//替换单个字符
echo str_replace('h','H',$str).'<br/>';//Hello world!
//替换多个字符(用数组)
$arry1 = array('h','d');
$arry2 = array('H','D');
echo str_replace($arry1,$arry2,$str);//Hello worlD!

// 2. PHP字符串比较函数:
//非自然比较,第一个字符串是小于10的数字,大于第二个字符串的第一个数字
echo strcmp('4','30').'<br/>';//1
//自然数比较
echo strnatcmp('4','30').'<br/>';//-1
//英文字符串比较
echo strcmp('hello','hello').'<br/>';//0
//不区分大小写
echo strcasecmp('hello','Hello').'<br/>';//0
//规定前几个数字进行比较
echo strncmp('2015','2016',3).'<br/>';//0
//两个字符串中相似字符的数量
echo similar_text('hello world','hello zym');//6

1.2.4. 字符串url解析和实体转换

// 1. 通过parse_url()解析url,并且返回其组成部分:
$str = 'http://www.baidu.com/admin?username=fxxy&pwd=123456';
echo '<pre>';
print_r(parse_url($str));
echo '<pre/>';
/*
  Array
  (
  [scheme] => http
  [host] => www.baidu.com
  [path] => /admin
  [query] => username=fxxy&pwd=123456
  )
*/
echo parse_url($str,PHP_URL_HOST);//www.baidu.com
echo parse_url($str,PHP_URL_PATH);// /admin

// 2. url编码和解码函数,对url的中文进行编码和解码:
$str = '疯行西月';
$a = urlencode($str);
echo "<a href='www.baidu.com/a..php?h=$a'>点击跳转</a>";//网址的中文部分变成了英文编码
echo urlencode($str);//  %E7%96%AF%E8%A1%8C%E8%A5%BF%E6%9C%88
echo urldecode(urlencode($str));//疯行西月

// 3. 将字符串转换为html实体:
$str = '<h1>疯行西月</h1>';
echo $str;//疯行西月
//转换中文
echo htmlentities($str);//<h1>疯行西月</h1>
echo htmlspecialchars($str);//不转换【中文】
echo htmlspecialchars_decode($str);//疯行西月

1.2.5. implode vs explode

// 将数组元素组合为字符串
$array = array('姓名', '电话', '电子邮箱');
$char = implode("^", $array);
echo $char;

// 将字符串转化为数组
$str = '姓名^电话^电子邮箱';
$arr = explode('^',$str);
print_r($arr);

1.2.6. 在字符串指定位置插入字符串

function str_insert($str,$i,$subStr){
    for($j=0;$j<$i;$j++){
    $startStr .=$str[$j];
    }
    for($j=$i;$j<strlen($str);$j++){
    $lastStr .= $str[$j];
    }
    $newStr = $startStr.$subStr.$lastStr;
    return $newStr;
}

1.3. 时间操作

1.3.1. 获取上个月第一天及最后一天

echo date('Y-m-01', strtotime('-1 month'));
echo date('Y-m-t', strtotime('-1 month'));
// 上个月第一天,  计算出本月第一天再减一个月
echo date('Y-m-d', strtotime(date('Y-m-01') . ' -1 month'));
// 上个月最后一天,// 计算出本月第一天再减一天
echo date('Y-m-d', strtotime(date('Y-m-01') . ' -1 day'));

1.3.2. 获取当月第一天及最后一天

$BeginDate=date('Y-m-01', strtotime(date("Y-m-d")));
echo date('Y-m-d', strtotime("$BeginDate +1 month -1 day"));

1.3.3. 获取当前年份、月份、日、天数

echo " 本月共有:".date("t")."天";
echo " 当前年份".date('Y');
echo " 当前月份".date('m');
echo " 当前几号".date('d');

1.3.4. 日期转时间戳,时间戳转日期

strtotime('2010-03-24 08:15:42');
date('Y-m-d H:i:s', 1156219870);

1.3.5. 计算已成为会员多少天或距离某活动还剩余多少天

function get_days_calc($calcTime, $currentTime, $differOrSurplus){
    switch ($differOrSurplus) {
    case 1:
    return round(($currentTime-$calcTime)/3600/24);
    break;
    case 2:
    return round(($calcTime-$currentTime)/3600/24);
    break;
    default:
    return round(($currentTime-$calcTime)/3600/24);
    break;
    }
}

1.4. 数组操作

1.4.1. 向二位数组中添加键值对

// 方法一
$tempArr=array();
foreach($arr as $key => $value){
    $value['new_key'] = $value['old_key1']+$value['old_key2'];
    $tempArr[] = $value;
}
// 方法二
foreach($arr as $key => $value){
    $arr[$key]['new_key'] = $value['old_key1']+$value['old_key2'];
}

1.4.2. 判断二维数组是否为空

// 判断一维数组是否为空
echo empty($array_test); //如果数组$array_test为空那么这个函数返回true
if($array_test){}; //如果数组为空.那么if的条件判断为false
echo count($array_test) //计算数组元素个数.为0就是空
echo sizeof($array_test) //count() 的别名 用法和返回一样

// 判断二维数组是否为空
function array_is_null($arr = null){
    if(is_array($arr)){
    foreach($arr as $k=>$v){
        if($v&&!is_array($v)){
        return false;
        }
        $t = self::array_is_null($v);
        if(!$t){
        return false;
        }
    }
    return true;
    }elseif(!$arr){
    return true;
    }else{
    return false;
    }
}

1.4.3. 求数组中各个元素之和

// 用foreach实现
$sum = 0;
foreach ($ar as $v) {
    $sum+=$v;
}
echo $sum;

// 用array_reduce实现
$result = array_reduce($arr, function leijia($a,$b){
    $a+=$b;
    return $a;
    });
echo $result;

// 将数组$arr的首个元素弹出,作为初始值,避免min($result['min'], $item['min'])中$result为空。否则最终结果min是空的。
$arr = array( 
    array('min' => 1.5456, 'max' => 2.28548, 'volume' => 23.152), 
    array('min' => 1.5457, 'max' => 2.28549, 'volume' => 23.152), 
    array('min' => 1.5458, 'max' => 2.28550, 'volume' => 23.152), 
    array('min' => 1.5459, 'max' => 2.28551, 'volume' => 23.152), 
    array('min' => 1.5460, 'max' => 2.28552, 'volume' => 23.152), 
); 

$initial = array_shift($arr); 

$t = array_reduce($arr, function($result, $item) { 
    $result['min'] = min($result['min'], $item['min']); 
    $result['max'] = max($result['max'], $item['max']); 
    $result['volume'] += $item['volume']; 

    return $result; 
}, $initial);

1.4.4. 取出两个数组中相同的内容

$arr1=array("0"=>"17","1"=>"20","2"=>"36","3"=>"48");
$arr2=array("0"=>"17","1"=>"36","3"=>"57");
$arr3=array_intersect($arr1,$arr2);
var_dump(array_unique($arr3));

1.4.5. 从数组中找到指定元素的位置

$array=array(2,3,4,1,5);
//找到3所处的位置
$find=3;

//第一种方式 循环解决 此举类似于 for while等循环
function find_by_foreach($array,$find)
{
    foreach ($array as $key => $v)
    {
    if($v==$find)
    {
        return $key;
    }
    }
}
//第二种方式 利用数组查找 找到所需要元素的索引位置
function find_by_array_search($array,$find)
{
    return array_search($find,$array);
}

//第三种方式 键值反转 通过值查找键
function find_by_array_flip($array,$find)
{
    $array=array_flip($array);
    return $array[$find];
}

var_dump(find_by_foreach($array,$find));
var_dump(find_by_array_search($array,$find));
var_dump(find_by_array_flip($array,$find));

1.4.6. 删除数组中指定值的元素的几种方法

// 1. 利用foreach和unset()函数删除数组中的特定元素
foreach($array as $k=>$v){
    if($v == 'day'){
    unset($array[$k]):
    }
}

// 2. 利用array_flip()函数和unset()函数删除数组中的特定值
$arr = array_flip($arr);
unset($arr['world']);

// 3. 利用array_search()和unset()函数删除数组中的特定值
if(($key = array_search('day',$arr))){
    unset($arr[$key]);
}

// 4. array_splice()函数可以与unset()函数起到相同作用
if(($key = array_search('day',$arr))){
    array_splice($arr, $key,1);
}

1.4.7. 根据某一个键值合并生成一个新的二维数组

$result= array();
foreach ($infos as $key => $info) {
    $result[$info['a']][] = $info;
}
print_r($result);

1.4.8. 无限级树

/**
 * 生成无限级树算法
 * @param  array  $arr                输入数组
 * @param  number $pid                根级的pid
 * @param  string $column_name        列名,id|pid父id的名字|children子数组的键名
 * @return array  $ret
 */
function make_tree($arr, $pid = 0, $column_name = 'id|pid|children') {
    list($idname, $pidname, $cldname) = explode('|', $column_name);
    $ret = array();
    foreach ($arr as $k => $v) {
    if ($v[$pidname] == $pid) {
        $tmp = $arr[$k];
        unset($arr[$k]);
        $tmp[$cldname] = make_tree($arr, $v[$idname], $column_name);
        $ret[] = $tmp;
    }
    }
    return $ret;
}

1.5. 文件操作

1.5.1. 下载文件

header("Content-type:text/html;charset=utf-8");
/**
 * 文件下载
 * @param  [type] $file_url [绝对路径,如:$_SERVER['DOCUMENT_ROOT'].'/upload/file/2019/01/18/test.png';]
 * @param  [type] $new_name [指定文件名称]
 * @return [type] [description]
 */
function downloadFile($file_url,$new_name=''){
    if(!isset($file_url)||trim($file_url) == ''){
    echo '500';
    }
    //检查文件是否存在
    if(!file_exists($file_url)){
    echo '404';
    }
    $file_name=basename($file_url);
    $file_type=explode('.',$file_url);
    $file_type=$file_type[count($file_type)-1];
    $file_name=trim($new_name=='')?$file_name:urlencode($new_name);
    $file_type=fopen($file_url,'r'); //打开文件
    //输入文件标签
    header("Content-type: application/octet-stream");
    header("Accept-Ranges: bytes");
    header("Accept-Length: ".filesize($file_url));
    header("Content-Disposition: attachment; filename=".$file_name);
    //输出文件内容
    echo fread($file_type,filesize($file_url));
    fclose($file_type);
}

几点注意事项

  • header("Content-type:text/html;charset=utf-8")的作用:在服务器响应浏览器的请求时,告诉浏览器以编码格式为UTF-8的编码显示该内容。
  • 关于file_exists()函数不支持中文路径的问题:因为php函数比较早,不支持中文,所以如果被下载的文件名是中文的话,需要对其进行字符编码转换,否则file_exists()函数不能识别,可以使用iconv()函数进行编码转换。
  • $file_sub_path() 我使用的是绝对路径,执行效率要比相对路径高。
  • Header("Content-type: application/octet-stream")的作用:通过这句代码客户端浏览器就能知道服务端返回的文件形式。
  • Header("Accept-Ranges: bytes")的作用:告诉客户端浏览器返回的文件大小是按照字节进行计算的。
  • Header("Accept-Length:".$file_size)的作用:告诉浏览器返回的文件大小。
  • Header("Content-Disposition: attachment; filename=".$file_name)的作用:告诉浏览器返回的文件的名称。
  • 以上四个Header()是必需的。
  • fclose($fp)可以把缓冲区内最后剩余的数据输出到磁盘文件中,并释放文件指针和有关的缓冲区

参考资料 Php如何实现下载功能超详细流程分析 php实现当前页面点击下载文件实例

1.5.2. 获取当前URL

function getCurrentPageURL()
{
    $pageURL = 'http';
    if (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on")
    {
    $pageURL .= "s";
    }
    $pageURL .= "://";
    if ($_SERVER["SERVER_PORT"] != "80")
    {
    $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
    }
    else
    {
    $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
    }
    return $pageURL;
}

1.5.3. curl 请求处理

function curl( $url = '',$method = 'GET',$req_data = false,$header = false,$response_header = false,$exec_time = 5,$connect_time = 5 )
{
    $method = strtoupper( $method );
    $ch = curl_init();
    // 设置请求url
    curl_setopt( $ch,CURLOPT_URL,$url );
    // 设置请求方法,默认执行GET请求,无需设置
    if( 'POST' == $method ){
    curl_setopt( $ch, CURLOPT_POST,1 );
    }elseif( 'GET' != $method ){
    curl_setopt( $ch, CURLOPT_CUSTOMREQUEST,$method );
    }
    // 设置请求头
    if( null != $header && is_array($header) ){
    curl_setopt( $ch,CURLOPT_HTTPHEADER,array_map(function($field,$value){
        return $field . ':' . $value;
    }, array_keys($header), $header) );
    }
    // 设置请请求数据
    if( null != $req_data && 'GET' != $method ){
    if ( is_array($req_data) && !isset($req_data['isfile']) ){
        $req_data = http_build_query($req_data);
    }
    curl_setopt( $ch,CURLOPT_POSTFIELDS,$req_data );
    }
    //设置输出数据中包含http header
    curl_setopt( $ch, CURLOPT_HEADER,$response_header );
    // 将curl_exec()获取的信息以字符串返回,而不是直接输出
    curl_setopt( $ch,CURLOPT_RETURNTRANSFER,true );
    // 允许 cURL 函数执行的最长秒数。
    curl_setopt( $ch,CURLOPT_TIMEOUT,$exec_time );
    //在尝试连接时等待的秒数。设置为0,则无限等待
    curl_setopt( $ch,CURLOPT_CONNECTTIMEOUT,$connect_time );
    // 执行curl请求
    $response = curl_exec($ch);
    //获取状态码
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    //关闭curl回话并释放资源
    curl_close($ch);
    //分离header与body
    if( $response_header ){
    $tmp         = explode("\r\n\r\n", $response);
    $resp_header = $tmp[0];
    $data        = $tmp[1];
    } else {
    $resp_header = null;
    $data        = $response;
    }
    $result['errcode'] = $status;
    $result['header']  = $resp_header;
    $result['data']    = $data;
    return $result;
}

1.6. 面向对象

1.6.1. 面向对象方法get_object_vars、is_subclass_of、interface_exists

  1. get_object_vars($obj) 获得对象的属性,以关联数组形式返回。
  2. get_parent_class(),参数是对象或者是类名,获得父类。
  3. is_subclass_of($obj,$class):判断对象是否是某个类的子类实例化产生的。
  4. interface_exists():判断接口是否存在。
  5. get_class():获得当前对象是哪个类实例化出来的。
  6. get_declared_classes():以数组形式返回当前脚本中所有的类。
  7. get_declared_interfaces():以数组形式返回当前脚本中的所有接口。
  8. method_exists():判断某个类中是否存在某个方法,也就是检查类的方法是否存在。
  9. property_exists():判断某个类中是否存在某个属性,也就是检查类的属性是否存在。
  10. instanceof:判断某个对象是否是某个类实例化产生的。

1.6.2. static, self, parent, and this

  1. static
    • static关键字声明一个属性或方法是和类相关的,而不是和类的某个特定的实例相关,因此,这类属性或方法也称为“类属性”或“类方法”。
    • static的属性,在内存中只有一份,为所有的实例共用。也就是说,在内存中即使有多个实例,静态的属性也只有一份。
    • static关键字可以用来修饰变量、方法。
    • 通过static关键字定义的属性或方法(例如static $web),只能由当前类通过【self::$web】来访问,其他类和子类是无法访问的。
  2. $this指的是实例化的对象,而不是类本身
  3. self指的是类本身,而不是实例化的对象
  4. 在PHP中,子类继承父类并改写了父类中的方法,但是依然想要调用父类中的方法,就用parent

1.6.3. trait

1.6.4. 魔术方法

  1. __construct(),类的构造函数
  2. __destruct(),类的析构函数
  3. __call(),在对象中调用一个不可访问方法时调用

    实例化的对象执行没有定义的方法或无权限访问的方法会报错,但是通过__call方法可以避免报错,并输出一些提示信息!
    
    class C{
        public function show(){
        echo 'show';
        }
        function __call($methodName/*方法名*/,$args/*参数*/){
        echo $methodName;
        }
    }
    $c = new C();
    $c->go();
    
  4. __callStatic(),用静态方式中调用一个不可访问方法时调用
  5. __get(),获得一个类的成员变量时调用,通过它可以在对象的外部获取私有成员属性的值。

    当调用一个权限上不允许调用的属性或不存在的属性时,__get魔术方法会自动调用,并且自动传参,参数值是属性名。
    
    class Person{
        public $name = 'fxxy';
        protected $age = 23;
        private $sex = 'man';
        function __get($var){
        echo '你想访问我的'.$var.'属性';
        }
    }
    $person = new Person();
    echo $person->name;//fxxy
    echo $person->age;//你想访问我的age属性
    echo $person->sex;//你想访问我的sex属性
    echo '<pre/>';
    print_r($person);
    
  6. __set(),设置一个类的成员变量时调用,用来设置私有属性值。

    当给一个权限上不允许直接访问或者是不存在的属性设置属性值时,__set魔术方法会自动调用
    
    class Person{
        public $name;
        protected $age;
        private $sex;
        public function __set($a,$b){
        echo '你想给我的'.$a.'赋值'.'并且值是'.$b.'<br/>';
        }
    }
    $person = new Person();
    $person->name = 'fxxy';//fxxy
    $person->age = '28';//你想给我的age赋值并且值是28
    $person->sex = 'man';//你想给我的sex赋值并且值是man
    echo $person->name.'<br/>';
    
  7. __isset(),当对private属性调用isset()或empty()时调用。

    用isset()判断某个某个属性属性是否存在时,__isset()自动执行。
    
  8. __unset(),当对private属性调用unset()时被调用。

    用unset()清除一个权限上不允许访问或者是不存在的属性时,__unset()自动执行。
    
  9. __sleep(),执行serialize()时,先会调用这个函数,然后才执行序列化操作。这个方法返回一个数组,数组元素就是类属性,可以包括全部的类属性,也可以随便包括其中的几个。
  10. __wakeup(),执行unserialize()时,先会调用这个函数,unserialize()函数可以重新还原一个被serialize()函数序列化的对象,__wakeup()方法则是恢复在序列中可能丢失的数据库连接及相关工作! 因为对象是存储在内存中的,为了提高程序运行效率,当某个对象使用完成之后,就会被垃圾回收机制回收,所以它不可能永久的保存在内存中,这样的话如果其他页面也需要用到这个对象,就比较困难了,这个时候可以把对象利用serialiaze()方法序列化,然后保存在到一个或数据库中,这样的话其他页面就可以随时调用了,然后想要删除这个序列化的对象也是很简单的。

    class Person{
        public $name;
        public $sex;
        private $age;
        public function __construct($name,$sex,$age){
        $this->name = $name;
        $this->sex = $sex;
        $this->age = $age;
        }
        public function __sleep(){
        return array('name','age');
        }
        public function __wakeup(){
        $age+=1;
        return $this->name;
        }
    }
    $person = new Person('fxxy','man',28);
    $p1 = serialize($person);
    echo $p1.'<br/>';
    $p2 = unserialize($p1);
    echo $p2->name;
    
  11. __toString(),类被当成字符串时的回应方法

    实例化的对象不可以直接用echo输出,但是如果类中有__toString方法,就可以输出相应的信息。
    
    class B{
        private $host;
        private $dbname;
        private $user;
        private $pwd;
        function __construct($host,$dbname,$user,$pwd){
        $this->host = $host;
        $this->dbname = $dbname;
        $this->user = $user;
        $this->pwd = $pwd;
        }
        public function connect(){
        echo '连接数据库';
        }
        public function gettable(){
        echo '获得表名';
        }
        public function insert(){
        echo '插入数据库';
        }
        function __toString(){
        $method = get_class_methods(__CLASS__);//获得当前类的所有方法(数组形式)
        $methodString = implode('、',$method);
        //return $methodString;//__construct、connect、gettable、insert、__toString
    
        $vars = get_object_vars($this);//获得当前对象的所有属性(数组形式)
        $varsString = implode('、',$vars);
        return $varsString;//localhost、mydb、admin、admin
        }
    }
    $b = new B('localhost','mydb','admin','admin');
    echo $b;//如果类中没有__toString方法会报错
    
    // 如果没有toString()方法,直接输出对象对发生致命性错误。
    // 注意:echo或print_r函数后面直接跟输出的对象,中间不要加其他多余的字符,否则__toString()方法不会被执行,例如这种情况:echo '输出对象'.$obj;
    
  12. __invoke(),调用函数的方式调用一个对象时的回应方法。
  13. __set_state(),调用var_export()导出类时,此静态方法会被调用。
  14. __clone(),当对象复制完成时调用(一个对象克隆另一个对象的时候)。

    __clone()里边的$this代表副本中的对象。$that代表原对象。
    
    class A{
        public $num = 1;
        public function show(){
        echo $this->num;//1
        }
        function __clone(){
        echo ++$this->num;//2
        }
    }
    $a = new A();
    
    $b = $a;
    echo intval($a===$b);//1
    
    echo $a->show();
    $b = clone $a;
    //echo intval($a===$b);//0,内容虽然一样,但是在内存中的地址不同
    
  15. __autoload(),尝试加载未定义的类

    其他的魔术方法都是在类中添加起作用,这是一个唯一不在类中添加的方法。
    只要在页面中使用到一个类,只要用到类名,就会自动将类名传给__autoload()的参数。
    

    代码示例

    // test.php
    function __autoload($className){
        include $className.'.class.php';
    }
    $one = new OneAction();
    $two = new TwoAction();
    $three = new ThreeAction();
    
    // OneAction.class.php
    class OneAction{
        public function __construct(){
        echo 'oneAction'.'<br/>';
        }
    }
    
    // TwoAction.class.php
    class TwoAction{
        public function __construct(){
        echo 'twoAction'.'<br/>';
        }
    }
    
    // ThreeAction.class.php
    class ThreeAction{
        public function __construct(){
        echo 'threeAction'.'<br/>';
        }
    }
    
    
  16. __debugInfo(),打印所需调试信息

1.7. 数据库相关

1.7.1. mysql, mysqli, pdo 区别

1.8. PHP 常用操作

1.8.1. PHP 生成唯一标识的方法

md5(time() . uniqid("", true));
function uuid($prefix ='')
{
    $chars = md5(uniqid(mt_rand(), true));
    $uuid = substr($chars,0,8) . '-';
    $uuid .= substr($chars,8,4) . '-';
    $uuid .= substr($chars,12,4) . '-';
    $uuid .= substr($chars,16,4) . '-';
    $uuid .= substr($chars,20,12);
    return $prefix . $uuid;
}

// 也可以使用SQL语句生成:
> insert into Price( Name, UUID, Price) values('FEIFEI_TEST', uuid(), 32);

1.8.2. PHP 手机号码中间4位加密

/**
 * 中间加密 字符串截取法
 */
public static function encryptTel($tel) {
    $new_tel = substr($tel, 0, 3).'****'.substr($tel, 7);
    return $new_tel;
}
/**
 * 中间加密 替换字符串的子串
 */
public static function encryptTel($tel) {
    $new_tel = substr_replace($tel, '****', 3, 4);
    return $new_tel;
}
/**
 * 中间加密 用正则
 */
public static function encryptTel($tel) {
    $new_tel = preg_replace('/(\d{3})\d{4}(\d{4})/', '$1****$2', $tel);
    return $new_tel;
}

1.8.3. 数值中去除无效的0

/**
 * 去除多余的0
 */
function del0($s)
{
    $s = trim(strval($s));
    if (preg_match('#^-?\d+?\.0+$#', $s)) {
    return preg_replace('#^(-?\d+?)\.0+$#','$1',$s);
    }
    if (preg_match('#^-?\d+?\.[0-9]+?0+$#', $s)) {
    return preg_replace('#^(-?\d+\.[0-9]+?)0+$#','$1',$s);
    }
    return $s;
}

1.8.4. 地图坐标转换

  1. 坐标系说明
    • WGS84:为一种大地坐标系,也是目前广泛使用的GPS全球卫星定位系统使用的坐标系;
    • GCJ02:表示经过国测局加密的坐标;
    • BD09:为百度坐标系,其中bd09ll表示百度经纬度坐标,bd09mc表示百度墨卡托米制坐标;
  2. 当前互联网地图的坐标系现状
    地球坐标 (WGS84)

    • 国际标准,从专业GPS 设备中取出的数据的坐标系
    • 国际地图提供商使用的坐标系

    火星坐标 (GCJ-02)也叫国测局坐标系

    • 中国标准:从国行移动设备中定位获取的坐标数据使用这个坐标系
    • 国家规定: 国内出版的各种地图系统(包括电子形式),必须至少采用GCJ-02对地理位置进行首次加密。

    百度坐标 (BD-09)

    • 百度标准,百度 SDK,百度地图,Geocoding 使用(本来就乱了,百度又在火星坐标上来个二次加密)。
  3. 开发注意事项
    • 从设备获取经纬度(GPS)坐标

      如果使用的是百度sdk那么可以获得百度坐标(bd09)或者火星坐标(GCJ02),默认是bd09    
      如果使用的是ios的原生定位库,那么获得的坐标是WGS84
      如果使用的是高德sdk,那么获取的坐标是GCJ02
      
    • 互联网在线地图使用的坐标系

      火星坐标系:
          iOS 地图(其实是高德)
          Gogole地图
          搜搜、阿里云、高德地图、腾讯地图
      百度坐标系:
          当然只有百度地图
      WGS84坐标系:
          国际标准,谷歌国外地图、osm地图等国外的地图一般都是这个
      
  4. GCJ02 <–> BD09

    <?php
    
    /**
     * 中国正常GCJ02坐标---->百度地图BD09坐标
     * 腾讯地图用的也是GCJ02坐标
     * @param double $lat 纬度
     * @param double $lng 经度
     */
    function Convert_GCJ02_To_BD09($lng,$lat){
        $x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        $x = $lng;
        $y = $lat;
        $z =sqrt($x * $x + $y * $y) + 0.00002 * sin($y * $x_pi);
        $theta = atan2($y, $x) + 0.000003 * cos($x * $x_pi);
        $lng = $z * cos($theta) + 0.0065;
        $lat = $z * sin($theta) + 0.006;
        return array('lng'=>$lng,'lat'=>$lat);
    }
    
    /**
     * 百度地图BD09坐标---->中国正常GCJ02坐标
     * 腾讯地图用的也是GCJ02坐标
     * @param double $lat 纬度
     * @param double $lng 经度
     * @return array();
     */
    function Convert_BD09_To_GCJ02($lng,$lat){
        $x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        $x = $lng - 0.0065;
        $y = $lat - 0.006;
        $z = sqrt($x * $x + $y * $y) - 0.00002 * sin($y * $x_pi);
        $theta = atan2($y, $x) - 0.000003 * cos($x * $x_pi);
        $lng = $z * cos($theta);
        $lat = $z * sin($theta);
        return ['lng'=>$lng,'lat'=>$lat];
    }
    

1.8.5. 跨域请求问题处理

1.8.5.1. 问题处理
// 客户端请求代码
// 上传文件
function upload_idcard_file(_this,type){
    var formData = new FormData();
    formData.append('type',type);
    formData.append('file',_this.files[0]);
    $.ajax({
        url: '{$upload_file_url}',
        type: 'POST',
        dataType: 'json',
        data: formData,
        cache: false,
        contentType : false,
        processData : false,
        headers : {"access_token" : "{$access_token}"},
        success:function(d){
            var img_url = d.data;
            img_url = 'http:'+img_url;
            load_img(_this.id,img_url);
        },
        error:function(err){
            console.log(err);
        }
    });
}
// 服务端处理:粗糙解决方式
// 允许所有跨域请求
header('Access-Control-Allow-Origin: *');

// 只允许 http://www.baidu.com 发来的跨域请求
// header('Access-Control-Allow-Origin: http://www.baidu.com');

// 设置支持的 http 请求方式
header('Access-Control-Allow-Methods:POST,GET,OPTIONS,PUT,DELETE');

// 允许的响应头字段,请按照自己需求添加
header('Access-Control-Allow-Headers:access_token');
if(isset($_SERVER['HTTP_ORIGIN'])){
    // 请求方法
    $request_method = $_SERVER['REQUEST_METHOD'];
    // 定义一个允许跨域请求接口的域名列表,这里你可以用配置也可以用其它形式,我这里只是用$GLOBALS简单演示一下
    $allow_origin = array(
    'baidu.com',
    'bing.com'
    );
    // 判断是否有origin请求头
    if(in_array($request_method, $allow_origin)
    {
        header('Access-Control-Allow-Origin: ' . $_SERVER['HTTP_ORIGIN']);
        // 客户端携带证书式访问。出于安全考虑,该项设置为true时,Access-Control-Allow-Origin 的值不允许为「*」
        header('Access-Control-Allow-Credentials: true'); 
        header('Access-Control-Allow-Methods:POST,GET,OPTIONS,PUT,DELETE');
        header('Access-Control-Allow-Headers:x-requested-with,content-type,access_token');
    }
    }
}
1.8.5.2. Session 跨域问题
ini_set('session.cookie_domain', '.a.com');
header('Access-Control-Allow-Credentials: true');

References

1.9. PHP 与 XML 技术

1.10. yield 语句是什么?yield 使用场景?yield 核心原理?

1.11. Slow array function used in loop

// Let's start with an example demonstrating the case:
$options = [];
foreach ($configurationSources as $source) {
    /* something happens here */
    $options = array_merge($options, $source->getOptions());
}

// In order to reduce execution time we can modify the code and perform the merge operation only once:
$options = [];
foreach ($configurationSources as $source) {
    /* something happens here */
    $options[] = $source->getOptions(); // <- yes, we'll use a little bit more memory
}

/* PHP below 5.6 */
$options = call_user_func_array('array_merge', $options + [[]]); // the nested empty array covers cases when no loops were made, must be second operand

/* PHP 5.6+: more friendly to refactoring as less magic involved */
$options = array_merge([], ...$options); // the empty array covers cases when no loops were made

/* PHP 7.4+: array_merge now accepts to be called without arguments. It will work even if $options is empty */
$options = array_merge(...$options);


// The second case demonstration:
for ($index = 0; $index < count($array); ++$index) {
    /* something happens here */
}

// Here count($array) is executed in each loop cycle and cause performance issues when counting big arrays. Instead, we can introduce a local variable, so the count operation gets executed only once:
for ($index = 0, $count = count($array); $index < $count; ++$index) {
    /* something happens here */
}

2. PHP 常见框架

2.1. ThinkPHP

2.2. Yii2 Framework

3. 附录 A:PHP 命名规范

3.1.

3.1.1. 类名称

  • 使用大写字母作为词的分割,其他的字母均使用小写。
  • 名字的首字母使用大写。
  • 不要使用下划线('_')。
如:Name、SuperMan、BigClassObject。

3.1.2. 类属性

属性名命名采用驼峰命名法(首字母小写,后续单词首字母大写),私有属性使用'_'开始。

如:$tablePrefix,$_tablePrefix

3.1.3. 类方法和函数名称

  • 方法的作用都是执行一个动作,达到一个目的。所以名称应该说明方法是做什么的。一般名称的前缀都是有第一规律的,如 is, get, set。
  • 方法的的命名采用驼峰命名法(首字母小写,后续单词首字母大写), 如:getUserName(), parseLayout()
  • 私有方法、函数,使用带有下划线的形式,如 _func()

3.1.4. 方法中参数

  • 参数命名采用驼峰命名法(首字母小写,后续单词首字母大写)。如:

    class EchoAnyWord{
        function echoWord($firstWord, $secondWord){
        ...
        }
    }
    

3.2. 变量和常量

  • 所有字母都使用小写。
  • 使用‘_’作为每个词的分界。
如:$msg_error、$chk_pwd等

3.2.1. 引用变量

  • 引用变量要带有‘r’(recommend)前缀。如:

    class Example{
        $mExam = "";
        funciton SetExam(&$rExam){
        ...
        }
        function $rGetExam(){
        ...
        }
    }
    

3.2.2. 全局变量

  • 全局变量应该带有前缀‘g’。如:global = $gTest、global = $g。

3.2.3. 常量

  • 常量、全局常量,应该全部使用大写字母,单词之间用‘_’来分割。如

    define('DEFAULT_NUM_AVE',90);
    define('DEFAULT_NUM_SUM',500);
    

3.2.4. 全局常量

  • 静态变量应该带有前缀‘s’。如:

    station $sStatus = 1;
    

3.2.5. 静态变量

  • 所有的名称都使用小写字母,多个单词使用‘_’来分割。如:

    function this_good_idear(){
        ...
    }
    

3.3. PSR-0 vs PSR-4

PSR,PHP Standards Recommendations。为自动加载而服务。目前官方已经废弃了 PSR-0,但是发现 composer 还是对 PSR-0 向下兼容,从 composer 的加载代码中了解了一下他们的区别:https://getcomposer.org/doc/04-schema.md#psr-4

4. 附录 B:PHP 预定义常量

常量名 常量值 说明
__FILE__ 当前的文件名 在哪个文件中使用,就代表哪个文件名称
__LINE__ 当前的行数 在代码的哪行使用,就代表哪行的行号
__FUNCTION__ 当前的函数名 在哪个函数中使用,就代表哪个函数名
__CLASS__ 当前的类名 在哪个类中使用,就代表哪个类的类名
__METHOD__ 当前对象的方法名 在对象中的哪个方法使用,就代表这个方法名
PHP_OS UNIX或WINNT等 执行PHP解析的操作系统名称
PHP_VERSION 5.5 当前php服务器的版本
TRUE TRUE 代表布尔值,真
FALSE FALSE 代表布尔值,假
NULL NULL 代表空值
DIRECTORY_SEPARATOR \或/ 根据操作系统决定目录的分隔符
PATH_SEPARATOR :或; 在linux上是一个":"号,WIN上是一个";"号
E_ERROR 1 错误,导致php脚本运行终止
E_WARNING 2 警告,不会导致php脚本运行终止
E_PARSE 4 解析错误,由程序解析器报告
E_NOTICE 8 非关键的错误,例如变量未初始化
M_PI 3.141592653 π 圆周率

5. 附录 C:PHP 函数

5.1. 数组函数

  • curl_setopt_array — 为 cURL 传输会话批量设置选项
  • array_change_key_case — 将数组中的所有键名修改为全大写或小写
  • array_chunk — 将一个数组分割成多个
  • array_column — 返回数组中指定的一列
  • array_combine — 创建一个数组,用一个数组的值作为其键名,另一个数组的值作为其值
  • array_count_values — 统计数组中所有的值
  • array_diff_assoc — 带索引检查计算数组的差集
  • array_diff_key — 使用键名比较计算数组的差集
  • array_diff_uassoc — 用用户提供的回调函数做索引检查来计算数组的差集
  • array_diff_ukey — 用回调函数对键名比较计算数组的差集
  • array_diff — 计算数组的差集
  • array_intersect_assoc — 带索引检查计算数组的交集
  • array_intersect_key — 使用键名比较计算数组的交集
  • array_intersect_uassoc — 带索引检查计算数组的交集,用回调函数比较索引
  • array_intersect_ukey — 用回调函数比较键名来计算数组的交集
  • array_intersect — 计算数组的交集

      // array_intersect ( array $array1 , array $array2 [, array $... ] ) : array
    // 去除空元素
    foreach($arr as $k=>$v){
        if(!$v) unset($arr[$k]);
    }
    ### 扩展学习:PHP从数组中删除元素的四种方法实例
    $array = array(0 => "a", 1 => "b", 2 => "c");
    // 1. 删除一个元素,且保持原有索引不变
    unset($array[1]);
    // 你想删除的key
    // 重排索引
    // 使用 array_values 函数:
    $array = array_values($array);
    // 2. 删除一个元素,不保持索引
    array_splice($array, 1, 1);
    // 你想删除的元素的Offset
    // 3. 按值删除多个元素,保持索引
    $array = array_diff($array, ["a", "c"]);
               //└────────┘→ 你想删除的数组元素值values
    // 4. 按键删除多个元素,保持索引
    $array = array_diff_key($array, [0 => "xy", "2" => "xy"]);
    // 你想删除的数组键keys
    
  • array_fill — 用给定的值填充数组
  • array_fill_keys — 使用指定的键和值填充数组
  • array_filter — 用回调函数过滤数组中的单元

    // array_filter ( array $array [, callable $callback [, int $flag = 0 ]] ) : array
    
  • array_flip — 交换数组中的键和值
  • array_key_exists — 检查数组里是否有指定的键名或索引
  • array_key_first — Gets the first key of an array
  • array_key_last — Gets the last key of an array
  • array_keys — 返回数组中部分的或所有的键名

    // array_flip ( array $array ) : array
    
  • array_map — 为数组的每个元素应用回调函数
  • array_walk_recursive — 对数组中的每个成员递归地应用用户函数
  • array_walk — 使用用户自定义函数对数组中的每个元素做回调处理

    // array_map ( callable $callback , array $array1 [, array $... ] ) : array
    
  • array_merge_recursive — 递归地合并一个或多个数组
  • array_merge — 合并一个或多个数组
  • array_reverse — 返回单元顺序相反的数组
  • array_pad — 以指定长度将一个值填充进数组
  • array_pop — 弹出数组最后一个单元(出栈)
  • array_product — 计算数组中所有值的乘积
  • array_push — 将一个或多个单元压入数组的末尾(入栈)
  • array_rand — 从数组中随机取出一个或多个单元
  • array_reduce — 用回调函数迭代地将数组简化为单一的值
  • array_replace_recursive — 使用传递的数组递归替换第一个数组的元素
  • array_replace — 使用传递的数组替换第一个数组的元素
  • array_search — 在数组中搜索给定的值,如果成功则返回首个相应的键名
  • array_slice — 从数组中取出一段
  • array_splice — 去掉数组中的某一部分并用其它值取代
  • array_sum — 对数组中所有值求和
  • array_udiff_assoc — 带索引检查计算数组的差集,用回调函数比较数据
  • array_udiff_uassoc — 带索引检查计算数组的差集,用回调函数比较数据和索引
  • array_udiff — 用回调函数比较数据来计算数组的差集
  • array_uintersect_assoc — 带索引检查计算数组的交集,用回调函数比较数据
  • array_uintersect_uassoc — 带索引检查计算数组的交集,用单独的回调函数比较数据和索引
  • array_uintersect — 计算数组的交集,用回调函数比较数据
  • array_unique — 移除数组中重复的值
  • array_shift — 将数组开头的单元移出数组
  • array_unshift — 在数组开头插入一个或多个单元
  • array_values — 返回数组中所有的值
  • array — 新建一个数组
  • compact — 建立一个数组,包括变量名和它们的值
  • count — 计算数组中的单元数目,或对象中的属性个数
  • current — 返回数组中的当前单元
  • each — 返回数组中当前的键/值对并将数组指针向前移动一步
  • end — 将数组的内部指针指向最后一个单元
  • extract — 从数组中将变量导入到当前的符号表
  • in_array — 检查数组中是否存在某个值
  • key_exists — 别名 array_key_exists
  • key — 从关联数组中取得键名
  • list — 把数组中的值赋给一组变量
  • next — 将数组中的内部指针向前移动一位
  • pos — current 的别名
  • prev — 将数组的内部指针倒回一位
  • range — 根据范围创建数组,包含指定的元素
  • reset — 将数组的内部指针指向第一个单元
  • shuffle — 打乱数组
  • sizeof — count 的别名

5.1.1. 排序函数

  • array_multisort — 对多个数组或多维数组进行排序
  • arsort — 对数组进行逆向排序并保持索引关系
  • asort — 对数组进行排序并保持索引关系
  • krsort — 对数组按照键名逆向排序
  • ksort — 对数组按照键名排序
  • sort — 对数组排序
  • rsort — 对数组逆向排序
  • natcasesort — 用“自然排序”算法对数组进行不区分大小写字母的排序
  • natsort — 用“自然排序”算法对数组排序
  • uasort — 使用用户自定义的比较函数对数组中的值进行排序并保持索引关联
  • uksort — 使用用户自定义的比较函数对数组中的键名进行排序
  • usort — 使用用户自定义的比较函数对数组中的值进行排序

        // uksort ( array &$array , callable $key_compare_func ) : bool
    uksort(&$arr, function ($a, $b) use ($seq) {
        $seq = array_flip($seq);
        $idx1 = $seq[$a] ?? -1;
        $idx2 = $seq[$b] ?? -1;
        return $idx1 - $idx2;
    });
    

5.2. 字符串函数

  • addcslashes — 以 C 语言风格使用反斜线转义字符串中的字符
  • addslashes(),字符串转义,使用反斜线引用字符串。如I’m Zhao中的’
  • bin2hex — 函数把包含数据的二进制字符串转换为十六进制值
  • chop — rtrim 的别名
  • chr — 返回指定的字符
  • chunk_split — 将字符串分割成小块
  • convert_cyr_string — 将字符由一种 Cyrillic 字符转换成另一种
  • convert_uudecode — 解码一个 uuencode 编码的字符串
  • convert_uuencode — 使用 uuencode 编码一个字符串
  • count_chars — 返回字符串所用字符的信息
  • crc32 — 计算一个字符串的 crc32 多项式
  • crypt — 单向字符串散列
  • echo — 输出一个或多个字符串
  • fprintf — 将格式化后的字符串写入到流
  • print_r — 以易于理解的格式打印变量。
  • var_dump — 打印变量的相关信息
  • var_export — 输出或返回一个变量的字符串表示

    print_r ( mixed $expression [, bool $return = FALSE ] ) : mixed
        var_dump ( mixed $expression [, mixed $... ] ) : void
        var_export ( mixed $expression [, bool $return ] ) : mixed
    
  • get_html_translation_table — 返回使用 htmlspecialchars 和 htmlentities 后的转换表
  • hebrev — 将逻辑顺序希伯来文(logical-Hebrew)转换为视觉顺序希伯来文(visual-Hebrew)
  • hebrevc — 将逻辑顺序希伯来文(logical-Hebrew)转换为视觉顺序希伯来文(visual-Hebrew),并且转换换行符
  • hex2bin — 转换十六进制字符串为二进制字符串
  • html_entity_decode — Convert HTML entities to their corresponding characters
  • htmlentities — 将字符转换为 HTML 转义字符
  • htmlspecialchars_decode — 将特殊的 HTML 实体转换回普通字符
  • htmlspecialchars — 将特殊字符转换为 HTML 实体 htmlentities 和 htmlspecialchars 的区别: 这两个函数的功能都是转换字符为 HTML 字符编码,特别是 url 和代码字符串。htmlentities 转换所有的 html 标记;htmlspecialchars 只格式化& ' " < 和 \> 这几个特殊符号。
  • lcfirst — 使一个字符串的第一个字符小写
  • levenshtein — 计算两个字符串之间的编辑距离
  • localeconv — Get numeric formatting information
  • ltrim — 删除字符串开头的空白字符(或其他字符)
  • md5_file — 计算指定文件的 MD5 散列值
  • md5 — 计算字符串的 MD5 散列值
  • metaphone — Calculate the metaphone key of a string
  • money_format — 将数字格式化成货币字符串
  • nl_langinfo — Query language and locale information
  • nl2br — 在字符串所有新行之前插入 HTML 换行标记
  • number_format — 以千位分隔符方式格式化一个数字

    // 无论值是否为0,都保留小数点后两位
    echo number_format((float)round($a,2,PHP_ROUND_HALF_ODD),2,'.','');
    // 整数部分以千位分隔符方式分隔
    echo number_format((float)round($a,2,PHP_ROUND_HALF_ODD),2,'.',',');
    
  • ord — 转换字符串第一个字节为 0-255 之间的值
  • parse_str — 将字符串解析成多个变量
  • print — 输出字符串
  • printf — 输出格式化字符串
  • quoted_printable_decode — 将 quoted-printable 字符串转换为 8-bit 字符串
  • quoted_printable_encode — 将 8-bit 字符串转换成 quoted-printable 字符串
  • quotemeta — 转义元字符集
  • rtrim — 删除字符串末端的空白字符(或者其他字符)
  • setlocale — 设置地区信息
  • sha1_file — 计算文件的 sha1 散列值
  • sha1 — 计算字符串的 sha1 散列值
  • similar_text — 计算两个字符串的相似度
  • soundex — Calculate the soundex key of a string
  • sprintf — Return a formatted string
  • sscanf — 根据指定格式解析输入的字符
  • str_getcsv — 解析 CSV 字符串为一个数组
  • str_ireplace — str_replace 的忽略大小写版本
  • str_pad — 使用另一个字符串填充字符串为指定长度
  • str_repeat — 重复一个字符串
  • str_rot13 — 对字符串执行 ROT13 转换
  • str_shuffle — 随机打乱一个字符串
  • str_split — 将字符串转换为数组
  • str_word_count — 返回字符串中单词的使用情况
  • strcasecmp — 二进制安全比较字符串(不区分大小写)
  • strcmp — 二进制安全字符串比较
  • strcoll — 基于区域设置的字符串比较
  • strcspn — 获取不匹配遮罩的起始子字符串的长度
  • strip_tags — 从字符串中去除 HTML 和 PHP 标记
  • stripcslashes — 反引用一个使用 addcslashes 转义的字符串
  • strpos(),查找字符串首次出现的位置。strpos ( string $haystack , mixed $needle [, int $offset = 0 ] ) : int,如果没找到 needle,将返回 FALSE,此函数可能返回布尔值 FALSE,但也可能返回等同于 FALSE 的非布尔值。应使用 = 运算符来测试此函数的返回值。缺点:对中文支持不好

    // 判断是否包含某字符串
    $pos = strpos($str,$needle);
    if($pos !== false){
          echo 'exist';
    }
    
  • stripslashes — 反引用一个引用字符串
  • strlen(),获取字符串长度。
  • strnatcasecmp — 使用“自然顺序”算法比较字符串(不区分大小写)
  • strnatcmp — 使用自然排序算法比较字符串
  • strncasecmp — 二进制安全比较字符串开头的若干个字符(不区分大小写)
  • strncmp — 二进制安全比较字符串开头的若干个字符
  • strpbrk — 在字符串中查找一组字符的任何一个字符
  • substr(),字符串截取。substr(字符串变量,开始截取的位置,截取个数) 。如:
  • mb_substr() ,字符串截取。mb_substr ( string $str , int $start [, int $length = NULL [, string $encoding = mb_internal_encoding() ]] ) : string
  • strstr(),返回字符串从查找字符串出现的位置开始到字符串结尾的字符串

    // 去除字符串后3位
    substr($tempStr,0,strlen($tempStr)-3);                                                   // 截取某个字符之后的字符串
    substr($str,strpos($str,"_");
    // 判断是否包含某字符串,没有返回值,则不包含
    echo strstr($str,'@');
    
  • stristr(),与 strstr() 的使用方法一样,区别是 stristr 不区分大小写。
  • strchr — strstr 的别名
  • strrchr — 查找指定字符在字符串中的最后一次出现
  • strrev — 反转字符串
  • strripos — 计算指定字符串在目标字符串中最后一次出现的位置(不区分大小写)
  • strspn — 计算字符串中全部字符都存在于指定字符集合中的第一段子串的长度。
  • strspn — 计算字符串中全部字符都存在于指定字符集合中的第一段子串的长度。
  • strstr — 查找字符串的首次出现
  • strtok — 标记分割字符串
  • strtolower — 将字符串转化为小写
  • strtoupper — 将字符串转化为大写
  • strtr — 转换指定字符
  • substr_compare — 二进制安全比较字符串(从偏移位置比较指定长度)
  • substr_count — 计算字串出现的次数
  • str_replace(),搜索替换字符串。substr_replace ( mixed $string , mixed $replacement , mixed $start [, mixed $length ] ) : mixed
  • trim — 去除字符串首尾处的空白字符(或者其他字符)
  • ucfirst — 将字符串的首字母转换为大写
  • ucwords — 将字符串中每个单词的首字母转换为大写
  • vfprintf — 将格式化字符串写入流
  • vprintf — 输出格式化字符串
  • vsprintf — 返回格式化字符串
  • wordwrap — 打断字符串为指定数量的字串
  • preg_replace(),搜索匹配替换字符串。Eg:搜索匹配到,,\n\r\s的使用|替换:preg_replace('[,,\s\r\n]+', '|', $ids);
  • sprintf(),格式化字符串。sprintf(格式,要转化的字符串),Eg:Sprintf('%01.2f',$str);
  • join — implode() 的别名

    // 判断是否包含某字符串
    $tempArr = explode(',',$str);
    if(count($tempArr) > 1){
        return true;
    }
    
  • htmlentities/htmlspecialchars/addslashes/stripslashes/strip_tags、mysql_real_escape_strin。
  • json_decode(),对 JSON 格式的字符串进行解码。
  • json_encode(),对变量进行 JSON 编码 。
  • strtolower(),把所有字符转换为小写
  • strtoupper(), 把所有字符转换为大写
  • strncmp() , 二进制安全比较字符串开头的若干个字符(区分大小写)

5.3. Math 函数

  • bcadd — [加]2个任意精度数字的加法计算
  • bcsub — [减]2个任意精度数字的减法
  • bcmul — [乘]2个任意精度数字乘法计算
  • bcdiv — [除]2个任意精度的数字除法计算

    $a = '1.234';
    $b = '5';
    echobcadd($a,$b, 4);  // 6.2340
    echobcsub($a, $b, 4);  // -3.7660
    echobcmul('1.34747474747', '35', 3); // 47.161
    

    PHP 高精度计算问题

    /*
      1. 引入
      javascript
      //为啥不等于 0.3 ? (正确结果:0.30000000000000004)
      0.1 + 0.2
      //为啥不等于 5.6 ? (正确结果:5.6000000000000005)
      0.8 * 7
      php
      // 正确结果是 57,而不是 58
      var_dump(intval(0.58 * 100));
      2. 原因分析
      浮点运算惹的祸,并非语言的 bug,但和语言的实现原理有关,不管什么语言,只要涉及浮点运算,都是存在类似的问题,使用时一定要注意。
      浮点数的表示(IEEE 754):浮点数, 以64位的长度(双精度)为例, 会采用1位符号位(E), 11指数位(Q), 52位尾数(M)表示(一共64位)。
      符号位:最高位表示数据的正负,0表示正数,1表示负数。
      指数位:表示数据以2为底的幂,指数采用偏移码表示。
      尾数:表示数据小数点后的有效数字。
      0.58的二进制表示是: 0.10010100011110101110000101000111101011100001010001111
      0.57的二进制表示是: 0.1001000111101011100001010001111010111000010100011111
      如果只是通过这52位计算的话,分别是:0.58 -> 0.57999999999999996,0.57 -> 0.5699999999999999。
      PHP浮点型在进行+-*%/存在不准确的问题,例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 7.9999999999...。
      3. 结论
      永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。如果确实需要更高的精度,应该使用任意精度数学函数或者 gmp 函数。
      浮点数精确位数取决于 PHP 配置参数 precision,默认 14 位,计算方式:从左第一个非0数就是精度的开始。
    */
    
  • bcmod — 对一个任意精度数字取模
  • bccomp — 比较两个任意精度的数字
  • bcpow — 任意精度数字的乘方
  • bcpowmod — Raise an arbitrary precision number to another, reduced by a specified modulus
  • bcscale — 设置所有bc数学函数的默认小数点保留位数
  • floatval(), 转换为浮点型
  • intval(),转换为整型
  • fmod — 返回除法的浮点数余数
  • intdiv — 对除法结果取整
  • bcsqrt — 任意精度数字的二次方根
  • sqrt — 平方根
  • is_finite — 判断是否为有限值
  • is_infinite — 判断是否为无限值
  • is_nan — 判断是否为合法数值
  • lcg_value — 组合线性同余发生器
  • log10 — 以 10 为底的对数
  • log1p — 返回 log(1 + number),甚至当 number 的值接近零也能计算出准确结果
  • log — 自然对数
  • max — 找出最大值
  • min — 找出最小值
  • exp — 计算 e 的指数
  • expm1 — 返回 exp(number) - 1,甚至当 number 的值接近零也能计算出准确结果
  • pi — 得到圆周率值
  • pow— 指数表达式,pow ( number $base , number $exp ) : number
  • cos — 余弦
  • cosh — 双曲余弦
  • sin — 正弦
  • sinh — 双曲正弦
  • tan — 正切
  • tanh — 双曲正切
  • acos — 反余弦
  • acosh — 反双曲余弦
  • asin — 反正弦
  • asinh — 反双曲正弦
  • atan2 — 两个参数的反正切
  • atan — 反正切
  • atanh — 反双曲正切
  • deg2rad — 将角度转换为弧度
  • rad2deg — 将弧度数转换为相应的角度数
  • mt_getrandmax — 显示随机数的最大可能值
  • mt_rand — 生成更好的随机数
  • mt_srand — 播下一个更好的随机数发生器种子
  • rand — 产生一个随机整数
  • srand — 播下随机数发生器种子
  • intval(), 直接取整,intval ( mixed $var [, int $base = 10 ] ) : int
  • round(), 四舍五入
  • ceil(),向上取整
  • floor(), 向下取整

      // intval()
      // 3
    echo intval(3.14);
    // round()
    // 格式:round ( float $val [, int $precision = 0 [, int $mode = PHP_ROUND_HALF_UP ]] ) : float
    //  PHP_ROUND_HALF_UP、 PHP_ROUND_HALF_DOWN PHP_ROUND_HALF_EVEN 或 PHP_ROUND_HALF_ODD
    $number = 1346.21;
     //float(1346.21)
    var_dump(round($number, 2));
    //float(1346)
    var_dump(round($number, 0));
    //float(1350)
    var_dump(round($number, -1));
    //float(1300)
    var_dump(round($number, -2));
     //10,四舍六入,遇5进1
    var_dump(round(9.5, 0, PHP_ROUND_HALF_UP));
    //9,四舍六入,遇5不舍弃
    var_dump(round(9.5, 0, PHP_ROUND_HALF_DOWN));
    //10,四舍六入,整数部分为奇数则进1
    var_dump(round(9.5, 0, PHP_ROUND_HALF_EVEN));
    //9,四舍六入,整数部分为偶数则进1
    var_dump(round(9.5, 0, PHP_ROUND_HALF_ODD));
    //9
    var_dump(round(8.5, 0, PHP_ROUND_HALF_UP));
    //8
    var_dump(round(8.5, 0, PHP_ROUND_HALF_DOWN));
    //8
    var_dump(round(8.5, 0, PHP_ROUND_HALF_EVEN));
    //9
    var_dump(round(8.5, 0, PHP_ROUND_HALF_ODD));
    // ceil()
    // 格式:ceil ( float $value ) : float
    // 4
    echo ceil(3.14);
    // floor()
    // 格式:floor ( float $value ) : float
    // 3
    echo floor(3.14);
    // 保留两位小数,不四舍五入
    var_dump(floor(3.157*100)/100));
    
  • bindec — 二进制转换为十进制
  • decbin — 十进制转换为二进制
  • dechex — 十进制转换为十六进制
  • decoct — 十进制转换为八进制
  • octdec — 八进制转换为十进制
  • hexdec — 十六进制转换为十进制
  • base_convert — 在任意进制之间转换数字

    // decbin ( int $number ) : string
    
  • hypot — 计算一直角三角形的斜边长度

5.4. 文件函数

  • basename — 返回路径中的文件名部分
  • chdir():更改当前操作目录
  • chgrp — 改变文件所属的组
  • chmod — 改变文件模式
  • chown — 改变文件的所有者
  • clearstatcache — 清除文件状态缓存
  • copy — 拷贝文件
  • closedir():关闭文件夹,参数是文件夹名称。
  • delete — 参见 unlink 或 unset
  • dirname — 返回当前文件路径中的目录部分,也就是当前文件/目录的所在目录。
  • disk_free_space — 返回目录中的可用空间
  • disk_total_space — 返回一个目录的磁盘总大小
  • file_exists — 检查文件或目录是否存在
  • filetype():判断文件或目录的类型
  • is_dir — 判断给定文件名是否是一个目录
  • mkdir — 创建一个文件夹,第一个参数是指定目录名,第二个参数是目录权限,第三个参数如果为true,则递归创建。
  • readlink — 返回符号连接指向的目标
  • realpath_cache_get — 获取真实目录缓存的详情
  • realpath_cache_size — 获取真实路径缓冲区的大小
  • realpath — 返回规范化的绝对路径名
  • rename — 重命名一个文件或目录
  • rmdir — 删除目录
  • getcwd():返回当前文件所在的目录
  • glob — 寻找与模式匹配的文件路径,以数组形式返回,参数1这个目录的所有内容,可以指定返回的具体类型。
  • pathinfo — 返回文件路径的信息
  • diskfreespace — disk_free_space 的别名
  • fclose — 关闭一个已打开的文件指针
  • feof — 测试文件指针是否到了文件结束的位置
  • fflush — 将缓冲内容输出到文件
  • fgetc — 从文件指针中读取字符
  • fgetcsv — 从文件指针中读入一行并解析 CSV 字段
  • fgets — 从文件指针中读取一行
  • fgetss — 从文件指针中读取一行并过滤掉 HTML 标记
  • filesize():得到文件大小,单位是字节
  • fputcsv — 将行格式化为 CSV 并写入文件指针
  • fputs — fwrite 的别名

    // fputcsv ( resource $handle , array $fields [, string $delimiter = ',' [, string $enclosure = '"' ]] ) : int
    // fgetcsv ( resource $handle [, int $length = 0 [, string $delimiter = ',' [, string $enclosure = '"' [, string $escape = '\\' ]]]] ) : array
    
  • opendir()打开文件夹,参数是文件夹路径。
  • readhdir():读取文件夹,参数是文件夹名称。
  • scandir('.'):以数组形式展示某个文件夹下的所有内容:
  • unlink():删除文件。rmdir():删除文件夹