開篇 · 從 PHP 函式說起
作為一門 Web 開發語言,PHP 無疑是成功的:
- 只需簡單的學習便可快速上手
- 內建大量系統函式
- 動態解釋型更快更靈活的應對業務快速迭代
- ……
今天,我們先從 PHP 的函式說起,用好這些系統內建函式,讓你的開發效率事半功倍。
1. array_column
1.1 提取指定列
相信很多 PHPer 對這個函式並不陌生,這個函式就是取陣列中的某一列,如
$records = array(
array(
'id' => 2135,'first_name' => 'John','last_name' => 'Doe',),array(
'id' => 3245,'first_name' => 'Sally','last_name' => 'Smith',array(
'id' => 5342,'first_name' => 'Jane','last_name' => 'Jones',array(
'id' => 5623,'first_name' => 'Peter',)
);
$first_names = array_column($records,'first_name');
print_r($first_names);
複製程式碼
結果為
Array
(
[0] => John
[1] => Sally
[2] => Jane
[3] => Peter
)
複製程式碼
1.2 指定列作鍵值對
如果我們需要提取last_name
,並用相應的id
作為鍵值,應該怎麼實現呢?你可能想到了foreach
迴圈,但用array_column()
可以一行程式碼搞定:
$last_names = array_column($records,'last_name','id');
print_r($last_names);
複製程式碼
輸出結果:
Array
(
[2135] => Doe
[3245 ] => Smith
[5342] => Jones
[5623] => Doe
)
複製程式碼
1.3 重新生成索引關係
我們還可以將每個使用者的 ID 作為$records
的key
重新生成索引陣列
$idRecords = array_column($records,null,'id');
print_r($idRecords);
複製程式碼
結果為:
Array
(
[2135] => Array
(
[id] => 2135
[first_name] => John
[last_name] => Doe
)
[3245] => Array
(
[id] => 3245
[first_name] => Sally
[last_name] => Smith
)
[5342] => Array
(
[id] => 5342
[first_name] => Jane
[last_name] => Jones
)
[5623] => Array
(
[id] => 5623
[first_name] => Peter
[last_name] => Doe
)
)
複製程式碼
1.4 從物件中獲取屬性
<?php
class User
{
public $username;
public function __construct(string $username)
{
$this->username = $username;
}
}
$users = [
new User('user 1'),new User('user 2'),new User('user 3'),];
print_r(array_column($users,'username'));
複製程式碼
結果為:
Array
(
[0] => user 1
[1] => user 2
[2] => user 3
)
複製程式碼
2. array_filter
array_filter()
將刪除 array 中所有等值為 FALSE
的條目。
var_dump(array_filter([0,0.0,'0','',false,[],true,123,'1']));
複製程式碼
結果為:
array(3) {
[7] =>
bool(true)
[8] =>
int(123)
[9] =>
string(1) "1"
}
複製程式碼
如果使用回撥函式,我們還可以做更多的事:
<?php
$employees = [
[
'name' => 'John','age' => 45,'language' => 'Python'
],[
'name' => 'Robbin','age' => 25,'language' => 'Golang'
],[
'name' => 'Smith','age' => 35,'language' => 'PHP'
],[
'name' => 'Steven','age' => 29,'language' => 'C#'
]
];
$fireList = array_filter(
$employees,function ($employee,$key) use (&$employees) {
return $employee['age'] > 35;
},ARRAY_FILTER_USE_BOTH
);
print_r($fireList);
複製程式碼
注意:使用者不應在回撥函式中修改陣列本身。例如增加/刪除單元或者對
array_filter()
正在作用的陣列進行unset
。如果陣列改變了,此函式的行為將不可預測。
2. array_map
通過array_map()
,我們可以通過預設的函式對陣列元素進行批量處理
function cube($n)
{
return($n * $n * $n);
}
$a = array(1,2,3,4,5);
$b = array_map("cube",$a);
print_r($b);
複製程式碼
$b
將輸出
Array
(
[0] => 1
[1] => 8
[2] => 27
[3] => 64
[4] => 125
)
複製程式碼
從PHP 5.3起,我們也可以將呼叫的函式寫作閉包的形式:
$b = array_map(
function ($n) {
return($n * $n * $n);
},$a
);
複製程式碼
同樣的,我們還可以使用系統內建的函式來處理一些資料,如:
$values = ['say',' bye',' to',' spaces ',' '];
$result = array_map('trim',$values);
複製程式碼
array_map()
也可以在類中使用,以下是在類中的呼叫方法
// Static outside of class context
array_map( array( 'ClassName','methodName' ),$array );
// Static inside class context
array_map( array( __CLASS__,$array );
array_map( array( 'self',$array );
// Non-static outside of object context
array_map( array( $object,$array );
// Non-static inside of object context
array_map( array( $this,$array );
複製程式碼
3. array_reduce
求 1 ~ 100 的和:
<?php
$hunder = range(1,100);
$sum = array_reduce(
$hunder,function ($carry,$item) {
$carry += $item;
return $carry;
}
);
echo $sum;
複製程式碼
4. array_walk
array_walk()
可以讓我們便捷的修改陣列內的元素:
$infos = [
['uid' => 1,'email' => '[email protected]'],['uid' => 2,'email' => '[email protected]']
];
array_walk(
$infos,function (&$info) {
$info['username'] = strstr($info['email'],'@',true);
unset($info['email']);
}
);
echo json_encode($infos); // [{"uid":1,"username":"jack"},{"uid":2,"username":"rose"}]
複製程式碼
5. array_walk_recursive
把任意維度的陣列轉換成一維陣列
$user = [
'a' => [100,'a1'],'b' => [101,'a2'],'c' => [
'd' => [102,'a3'],'e' => [103,'a4']
]
];
function array_flat($arr) {
$result = [];
array_walk_recursive($arr,function ($value) use (&$result) {
array_push($result,$value);
});
return $result;
}
print_r(array_flat($user));
複製程式碼
6. filter_var
// 驗證郵箱
var_dump(filter_var('[email protected]',FILTER_VALIDATE_EMAIL)); // 有效輸出email地址,無效輸出false
// 驗證 IPv4
var_dump(filter_var('8.8.8.8',FILTER_VALIDATE_IP,FILTER_FLAG_IPV4)); // 有效輸出IP,無效輸出false
// 驗證 IPv6
var_dump(filter_var('2001:4860:4860::8888',FILTER_FLAG_IPV6)); // 有效輸出IP,無效輸出false
// 驗證非私網 IP
var_dump(filter_var('10.0.0.1',FILTER_FLAG_NO_PRIV_RANGE)); // 非私網輸出IP,否則輸出false
var_dump(filter_var('192.0.0.1',FILTER_FLAG_NO_PRIV_RANGE));
// 驗證非保留 IP
var_dump(filter_var('8.8.8.8',FILTER_FLAG_NO_RES_RANGE)); // // 非保留IP輸出IP,否則輸出false
var_dump(filter_var('127.0.0.1',FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var('0.0.0.0',FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var('169.254.0.0',FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var('255.255.255.255',FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var('::1',FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var('2002',FILTER_FLAG_NO_RES_RANGE));
// 驗證 Mac 地址
var_dump(filter_var('F1:5C:89:A4:40:49',FILTER_VALIDATE_MAC)); // 有效輸出地址,無效輸出 false
// 驗證布林值
var_dump(filter_var('1',FILTER_VALIDATE_BOOLEAN)); // 1,true,on,yes 返回 true,否則返回 false
// 驗證浮點數
var_dump(filter_var('1234.233',FILTER_VALIDATE_FLOAT)); // 有效輸出浮點數,無效輸出 false
var_dump(filter_var('1,234.233',FILTER_VALIDATE_FLOAT,FILTER_FLAG_ALLOW_THOUSAND));
複製程式碼
7. array_multisort
通過array_multisort()
,可以讓我們像操作 Excel 一樣對資料進行排序操作,我們先來看一個簡單的例子
7.1 多個陣列排序
$ar1 = array(10,100,0);
$ar2 = array(1,4);
array_multisort($ar1,$ar2);
var_dump($ar1);
var_dump($ar2);
複製程式碼
這個例子裡,排序後,第一個陣列會包含 0、 10、 100、 100。 第二個陣列會包含 4、1、 2、 3。 第二個陣列裡的專案對應第一個陣列後也進行了排序(100 和 100)。
array(4) {
[0]=> int(0)
[1]=> int(10)
[2]=> int(100)
[3]=> int(100)
}
array(4) {
[0]=> int(4)
[1]=> int(1)
[2]=> int(2)
[3]=> int(3)
}
複製程式碼
7.2 對資料庫結果進行排序
現在資料表中儲存著如下的資料:
volume | edition
-------+--------
67 | 2
86 | 1
85 | 6
98 | 2
86 | 6
67 | 7
複製程式碼
我們將 volume 降序排列,把 edition 升序排列
$data = [
['volume' => 67,'edition' => 2],['volume' => 86,'edition' => 1],['volume' => 85,'edition' => 6],['volume' => 98,['volume' => 67,'edition' => 7],];
// 取得列的列表
$volume = array_column($data,'volume');
$edition = array_column($data,'edition');
// 將資料根據 volume 降序排列,根據 edition 升序排列
// 把 $data 作為最後一個引數,以通用鍵排序
array_multisort($volume,SORT_DESC,$edition,SORT_ASC,$data);
複製程式碼
資料集合現在排好序了,結果如下:
volume | edition
-------+--------
98 | 2
86 | 1
86 | 6
85 | 6
67 | 2
67 | 7
複製程式碼
8. array_merge
這個應該都很熟悉,就是將兩個陣列合並:
$array1 = array("color" => "red",4);
$array2 = array("a","b","color" => "green","shape" => "trapezoid",4);
print_r(array_merge($array1,$array2));
複製程式碼
輸出
Array
(
[color] => green
[0] => 2
[1] => 4
[2] => a
[3] => b
[shape] => trapezoid
[4] => 4
)
複製程式碼
⚠️:如果合併的陣列中包含了關聯陣列,則相同鍵名元素會覆蓋,且合併後的陣列保留原鍵名。若是索引陣列,則會重新生成索引。
同名關聯陣列被覆蓋:
$array1 = array("color" => "red");
$array2 = array("color" => "green","shape" => "trapezoid");
print_r(array_merge($array1,$array2));
複製程式碼
輸出
Array
(
[color] => green
[shape] => trapezoid
)
複製程式碼
同名索引陣列重新索引:
$array1 = array(2,$array2));
複製程式碼
輸出
Array
(
[0] => 2
[1] => 4
[2] => a
[3] => b
[4] => 4
)
複製程式碼
還有另一種合併陣列的方式:+
運運算元,這種方式可以完全保留原有陣列並將新的陣列附加到後面。在兩個陣列中存在相同的鍵名時,第一個陣列中的同鍵名的元素將會被保留,第二個陣列中的元素將會被忽略
$array1 = array(0 => 'zero_a',2 => 'two_a',3 => 'three_a');
$array2 = array(1 => 'one_b',3 => 'three_b',4 => 'four_b');
$result = $array1 + $array2;
print_r($result);
複製程式碼
輸出
Array
(
[0] => zero_a
[2] => two_a
[3] => three_a
[1] => one_b
[4] => four_b
)
複製程式碼
9. array_merge_recursive
將相同 key
的不同陣列中資訊進行合併:
<?php
$baseInfo = [
'jack' => [
'age' => 22,'tel' => '56710937'
],'rose' => [
'age' => 21,'tel' => '578391038'
]
];
$extInfo = [
'jack' => [
'addrs' => 'NYC'
],'rose' => [
'addrs' => 'London'
]
];
echo json_encode(array_merge_recursive($baseInfo,$extInfo));
複製程式碼
輸出:
{
"jack":{
"age":22,"tel":"56710937","addrs":"NYC"
},"rose":{
"age":21,"tel":"578391038","addrs":"London"
}
}
複製程式碼
10. range
生成指定區間的陣列
range(0,100);
複製程式碼
指定步長為 10
range(1,100,10); // [0,10,20,30,40,50,60,70,80,90,100]
複製程式碼
如果起始值大於結束值,則會按照遞減的順序生成
range(100,10); // [100,0]
複製程式碼
三個引數也可以是浮點數
range(12.8,2.2,2.5); // [12.8,10.3,7.8,5.3,2.8]
複製程式碼
$start
和 $end
如果全部是字串,那麼會取兩個字串的第一個字母,並按照 ASCII 字母順序表,取步長對應的值
range('a','i'); // ["a","c","d","e","f","g","h","i"]
複製程式碼
那麼,我們如何使用range()
來輸出 ASCII 的所有可見字元呢?,這在PHP中非常簡單:
range(' ','~');
複製程式碼
11. array_chunk
如果我們需要將一個陣列拆分為多個陣列,就可以通過array_chunk()
快速實現:
<?php
$input_array = array('a','b','c','d','e');
echo json_encode(array_chunk($input_array,2)),PHP_EOL;
echo json_encode(array_chunk($input_array,true));
// [["a","b"],["c","d"],["e"]]
// [["a",{"2":"c","3":"d"},{"4":"e"}]
複製程式碼
12. array_combine
現在有兩個陣列,我們希望一個陣列的元素做key
,另一個陣列的元素做value
,合併為一個陣列:
$a = array('green','red','yellow');
$b = array('avocado','apple','banana');
$c = array_combine($a,$b);
echo json_encode($c);
// {"green":"avocado","red":"apple","yellow":"banana"}
複製程式碼
13. extract
14. compact
15. array_diff & array_intersect
如果需要求陣列元素的差集/交集,可以使用array_diff($array1,$array2[,$arrayn])
,這將返回存在於$array1
中而不存在其他 array 中值。
<?php
$array1 = array("a" => "green","red","blue","red");
$array2 = array("b" => "green","yellow","red");
$diff = array_diff($array1,$array2);
$intersect = array_intersect($array1,$array2);
echo json_encode($diff); // {"1":"blue"}
echo json_encode($diff); // {"a":"green","0":"red","2":"red"}
複製程式碼
16. array_diff_key & array_intersect_key
顧名思義,使用鍵名計算陣列的差集/交集,同樣是返回存在於$array1
中而不存在與其他$array
中的值。
17. array_diff_assoc & array_intersect_assoc
該函式會將鍵名與元素都作為比較條件。
18. version_compare
預設情況下,在第一個版本低於第二個時,version_compare() 返回 -1;如果兩者相等,返回 0;第二個版本更低時則返回 1。(類似於太空操作符)))
echo version_compare('5.3.0','7.1.4'); // -1
複製程式碼
19. number_format
該函式用於格式化數字,能實現
- 是否保留小數
- 數字的精度
- 自定義千分位分隔符與小數點分隔符
$num = 123456.789;
echo number_format($num),PHP_EOL;
echo number_format($num,2),1,',','/'),PHP_EOL;
複製程式碼
20. trim
tirm()
可以去除字串首尾處的空白字元(或者其他字元),如果沒有指定待刪除的字元列表,則會刪除以下字元:
- " " (ASCII 32 (0x20)),普通空格符。
- "\t" (ASCII 9 (0x09)),製表符。
- "\n" (ASCII 10 (0x0A)),換行符。
- "\r" (ASCII 13 (0x0D)),回車符。
- "\0" (ASCII 0 (0x00)),空位元組符。
- "\x0B" (ASCII 11 (0x0B)),垂直製表符。
通常情況下,我們都會指定刪除的字元列表
trim('@apple……','@#¥%……'); // apple
複製程式碼
tips: 該函式與array_map()
同時服用,效果更佳。