經常使用一種語言的話大家都會總結一些自己常用的一些函數和功能,本文介紹9個常用的PHP函數功能。其中有些是非常有用的,但沒有得到充分利用,內容如下:
1、任意參數數目的函數
你可能已經知道,PHP 允許定義可選參數的函數。但也有完全允許任意數目的函數參數的方法。以下是可選參數的例子:
以下為引用的內容:
// function with 2 optional arguments
function foo($arg1 = '', $arg2 = '') {
echo "arg1: $arg1\n";
echo "arg2: $arg2\n";
}
foo('hello','world');
/* prints:
arg1: hello
arg2: world
*/
foo();
/* prints:
arg1:
arg2:
*/
現在讓我們看看如何建立能夠接受任何參數數目的函數。這一次需要使用 func_get_args() 函數:
以下為引用的內容:
// yes, the argument list can be empty
function foo() {
// returns an array of all passed arguments
$args = func_get_args();
foreach ($args as $k => $v) {
echo "arg".($k+1).": $v\n";
}
}
foo();
/* prints nothing */
foo('hello');
/* prints
arg1: hello
*/
foo('hello', 'world', 'again');
/* prints
arg1: hello
arg2: world
arg3: again
*/
2、使用 Glob() 查找文件
許多 PHP 函數具有長描述性的名稱。然而可能會很難說出 glob() 函數能做的事情,除非你已經通過多次使用並熟悉了它。可以把它看作是比 scandir() 函數更強大的版本,可以按照某種模式搜索文件。
以下為引用的內容:
// get all PHP files
$files = glob('*.PHP');
print_r($files);
/* output looks like:
Array
(
[0] => phptest.PHP
[1] => pi.PHP
[2] => post_output.PHP
[3] => test.PHP
)
*/
你可以像這樣獲得多個文件:
以下為引用的內容:
// get all PHP files AND txt files
$files = glob('*.{PHP,txt}', GLOB_BRACE);
print_r($files);
/* output looks like:
Array
(
[0] => phptest.PHP
[1] => pi.PHP
[2] => post_output.PHP
[3] => test.PHP
[4] => log.txt
[5] => test.txt
)
*/
請注意,這些文件其實是可以返回一個路徑,這取決於查詢條件:
以下為引用的內容:
$files = glob('../images/a*.jpg');
print_r($files);
/* output looks like:
Array
(
[0] => ../images/apple.jpg
[1] => ../images/art.jpg
)
*/
如果你想獲得每個文件的完整路徑,你可以調用 realpath() 函數:
以下為引用的內容:
$files = glob('../images/a*.jpg');
// applIEs the function to each array element
$files = array_map('realpath',$files);
print_r($files);
/* output looks like:
Array
(
[0] => C:\wamp\www\images\apple.jpg
[1] => C:\wamp\www\images\art.jpg
)
*/
3、內存使用信息
通過偵測腳本的內存使用情況,有利於代碼的優化。PHP 提供了一個垃圾收集器和一個非常復雜的內存管理器。腳本執行時所使用的內存量,有升有跌。為了得到當前的內存使用情況,我們可以使用 memory_get_usage() 函數。如果需要獲得任意時間點的最高內存使用量,則可以使用 memory_limit() 函數。
以下為引用的內容:
echo "Initial: ".memory_get_usage()." bytes \n";
/* prints
Initial: 361400 bytes
*/
// let's use up some memory
for ($i = 0; $i < 100000; $i++) {
$array []= md5($i);
}
// let's remove half of the array
for ($i = 0; $i < 100000; $i++) {
unset($array[$i]);
}
echo "Final: ".memory_get_usage()." bytes \n";
/* prints
Final: 885912 bytes
*/
echo "Peak: ".memory_get_peak_usage()." bytes \n";
/* prints
Peak: 13687072 bytes
*/
4、CPU 使用信息
為此,我們要利用 getrusage() 函數。請記住這個函數不適用於 Windows 平台。
以下為引用的內容:
print_r(getrusage());
/* prints
Array
(
[ru_oublock] => 0
[ru_inblock] => 0
[ru_msgsnd] => 2
[ru_msgrcv] => 3
[ru_maxrss] => 12692
[ru_ixrss] => 764
[ru_idrss] => 3864
[ru_minflt] => 94
[ru_majflt] => 0
[ru_nsignals] => 1
[ru_nvcsw] => 67
[ru_nivcsw] => 4
[ru_nswap] => 0
[ru_utime.tv_usec] => 0
[ru_utime.tv_sec] => 0
[ru_stime.tv_usec] => 6269
[ru_stime.tv_sec] => 0
)
*/這可能看起來有點神秘,除非你已經有系統管理員權限。以下是每個值的具體說明(你不需要記住這些):
以下為引用的內容:
ru_oublock: block output Operations
ru_inblock: block input Operations
ru_msgsnd: messages sent
ru_msgrcv: messages received
ru_maxrss: maximum resident set size
ru_ixrss: integral shared memory size
ru_idrss: integral unshared data size
ru_minflt: page reclaims
ru_majflt: page faults
ru_nsignals: signals received
ru_nvcsw: voluntary context switches
ru_nivcsw: involuntary context switches
ru_nswap: swaps
ru_utime.tv_usec: user time used (microseconds)
ru_utime.tv_sec: user time used (seconds)
ru_stime.tv_usec: system time used (microseconds)
ru_stime.tv_sec: system time used (seconds)
要知道腳本消耗多少 CPU 功率,我們需要看看 ‘user time’ 和 ’system time’ 兩個參數的值。秒和微秒部分默認是單獨提供的。你可以除以 100 萬微秒,並加上秒的參數值,得到一個十進制的總秒數。讓我們來看一個例子:
以下為引用的內容:
// sleep for 3 seconds (non-busy)
sleep(3);
$data = getrusage();
echo "User time: ".
($data['ru_utime.tv_sec'] +
$data['ru_utime.tv_usec'] / 1000000);
echo "System time: ".
($data['ru_stime.tv_sec'] +
$data['ru_stime.tv_usec'] / 1000000);
/* prints
User time: 0.011552
System time: 0
*/
盡管腳本運行用了大約 3 秒鐘,CPU 使用率卻非常非常低。因為在睡眠運行的過程中,該腳本實際上不消耗 CPU 資源。還有許多其他的任務,可能需要一段時間,但不占用類似等待磁盤操作等 CPU 時間。因此正如你所看到的,CPU 使用率和運行時間的實際長度並不總是相同的。下面是一個例子:
以下為引用的內容:
// loop 10 million times (busy)
for($i=0;$i<10000000;$i++) {
}
$data = getrusage();
echo "User time: ".
($data['ru_utime.tv_sec'] +
$data['ru_utime.tv_usec'] / 1000000);
echo "System time: ".
($data['ru_stime.tv_sec'] +
$data['ru_stime.tv_usec'] / 1000000);
/* prints
User time: 1.424592
System time: 0.004204
*/
這花了大約 1.4 秒的 CPU 時間,但幾乎都是用戶時間,因為沒有系統調用。系統時間是指花費在執行程序的系統調用時的 CPU 開銷。下面是一個例子:
以下為引用的內容:
$start = microtime(true);
// keep calling microtime for about 3 seconds
while(microtime(true) - $start < 3) {
}
$data = getrusage();
echo "User time: ".
($data['ru_utime.tv_sec'] +
$data['ru_utime.tv_usec'] / 1000000);
echo "System time: ".
($data['ru_stime.tv_sec'] +
$data['ru_stime.tv_usec'] / 1000000);
/* prints
User time: 1.088171
System time: 1.675315
*/
現在我們有相當多的系統時間占用。這是因為腳本多次調用 microtime() 函數,該函數需要向操作系統發出請求,以獲取所需時間。你也可能會注意到運行時間加起來不到 3 秒。這是因為有可能在服務器上同時存在其他進程,並且腳本沒有 100% 使用 CPU 的整個 3 秒持續時間。
5、魔術常量
PHP 提供了獲取當前行號 (__LINE__)、文件路徑 (__FILE__)、目錄路徑 (__DIR__)、函數名 (__FUNCTION__)、類名 (__CLASS__)、方法名 (__METHOD__) 和命名空間 (__NAMESPACE__) 等有用的魔術常量。在這篇文章中不作一一介紹,但是我將告訴你一些用例。當包含其他腳本文件時,使用 __FILE__ 常量(或者使用 PHP5.3 新具有的 __DIR__ 常量):
以下為引用的內容:
// this is relative to the loaded script's path
// it may cause problems when running scripts from different directorIEs
require_once('config/database.PHP');
// this is always relative to this file's path
// no matter where it was included from
require_once(dirname(__FILE__) . '/config/database.PHP');
使用 __LINE__ 使得調試更為輕松。你可以跟蹤到具體行號。
以下為引用的內容:
// some code
// ...
my_debug("some debug message", __LINE__);
/* prints
Line 4: some debug message
*/
// some more code
// ...
my_debug("another debug message", __LINE__);
/* prints
Line 11: another debug message
*/
function my_debug($msg, $line) {
echo "Line $line: $msg
6、生成唯一標識符
某些場景下,可能需要生成一個唯一的字符串。我看到很多人使用 md5() 函數,即使它並不完全意味著這個目的:
以下為引用的內容:
// generate unique string
echo md5(time() . mt_rand(1,1000000));
There is actually a PHP function named uniqid() that is meant to be used for this.
// generate unique string
echo uniqid();
/* prints
4bd67c947233e
*/
// generate another unique string
echo uniqid();
/* prints
4bd67c9472340
*/
你可能會注意到,盡管字符串是唯一的,前幾個字符卻是類似的,這是因為生成的字符串與服務器時間相關。但實際上也存在友好的一方面,由於每個新生成的 ID 會按字母順序排列,這樣排序就變得很簡單。為了減少重復的概率,你可以傳遞一個前綴,或第二個參數來增加熵:
以下為引用的內容:
// with prefix
echo uniqid('foo_');
/* prints
foo_4bd67d6cd8b8f
*/
// with more entropy
echo uniqid('',true);
/* prints
4bd67d6cd8b926.12135106
*/
// both
echo uniqid('bar_',true);
/* prints
bar_4bd67da367b650.43684647
*/
這個函數將產生比 md5() 更短的字符串,能節省一些空間。
7、序列化
你有沒有遇到過需要在數據庫或文本文件存儲一個復雜變量的情況?你可能沒能想出一個格式化字符串並轉換成數組或對象的好方法,PHP 已經為你准備好此功能。有兩種序列化變量的流行方法。下面是一個例子,使用 serialize() 和 unserialize() 函數:
以下為引用的內容:
// a complex array
$myvar = array(
'hello',
42,
array(1,'two'),
'apple'
);
// convert to a string
$string = serialize($myvar);
echo $string;
/* prints
a:4:{i:0;s:5:"hello";i:1;i:42;i:2;a:2:{i:0;i:1;i:1;s:3:"two";}i:3;s:5:"apple";}
*/
// you can reproduce the original variable
$newvar = unserialize($string);
print_r($newvar);
/* prints
Array
(
[0] => hello
[1] => 42
[2] => Array
(
[0] => 1
[1] => two
)
[3] => apple
)
*/
這是原生的 PHP 序列化方法。然而,由於 JSON 近年來大受歡迎,PHP5.2 中已經加入了對 JSON 格式的支持。現在你可以使用 json_encode() 和 JSon_decode() 函數:
以下為引用的內容:
// a complex array
$myvar = array(
'hello',
42,
array(1,'two'),
'apple'
);
// convert to a string
$string = JSon_encode($myvar);
echo $string;
/* prints
["hello",42,[1,"two"],"apple"]
*/
// you can reproduce the original variable
$newvar = JSon_decode($string);
print_r($newvar);
/* prints
Array
(
[0] => hello
[1] => 42
[2] => Array
(
[0] => 1
[1] => two
)
[3] => apple
)
*/
這將更為行之有效,尤其與 JavaScript 等許多其他語言兼容。然而對於復雜的對象,某些信息可能會丟失。