那些未曾了解的PHP函數(shù)和功能
PHP的真正威力源自于它的函數(shù),但有些PHP函數(shù)并沒有得到充分的利用,也并不是所有人都會從頭到尾一頁一頁地閱讀手冊和函數(shù)參考,這里將向您介紹這些實用的函數(shù)和功能。
51CTO推薦專題: PHP開發(fā)基礎(chǔ)入門
1、任意參數(shù)數(shù)目的函數(shù)
你可能已經(jīng)知道,PHP允許定義可選參數(shù)的函數(shù)。但也有完全允許任意數(shù)目的函數(shù)參數(shù)的方法。以下是可選參數(shù)的例子:
- 以下為引用的內(nèi)容:
- //functionwith2optionalarguments
- functionfoo($arg1=”,$arg2=”){
- echo“arg1:$arg1\n”;
- echo“arg2:$arg2\n”;
- }
- foo(‘hello’,'world’);
- /*prints:
- arg1:hello
- arg2:world
- */
- foo();
- /*prints:
- arg1:
- arg2:
- */
現(xiàn)在讓我們看看如何建立能夠接受任何參數(shù)數(shù)目的函數(shù)。這一次需要使用func_get_args()函數(shù):
- 以下為引用的內(nèi)容:
- //yes,theargumentlistcanbeempty
- functionfoo(){
- //returnsanarrayofallpassedarguments
- $args=func_get_args();
- foreach($argsas$k=>$v){
- echo“arg”.($k+1).”:$v\n”;
- }
- }
- foo();
- /*printsnothing*/
- foo(‘hello’);
- /*prints
- arg1:hello
- */
- foo(‘hello’,‘world’,‘again’);
- /*prints
- arg1:hello
- arg2:world
- arg3:again
- */
#p#
2、使用Glob()查找文件
許多PHP函數(shù)具有長描述性的名稱。然而可能會很難說出glob()函數(shù)能做的事情,除非你已經(jīng)通過多次使用并熟悉了它??梢园阉醋魇潜萻candir()函數(shù)更強大的版本,可以按照某種模式搜索文件。
- 以下為引用的內(nèi)容:
- //getallphpfiles
- $files=glob(‘*.php’);
- print_r($files);
- /*outputlookslike:
- Array
- (
- [0]=>phptest.php
- [1]=>pi.php
- [2]=>post_output.php
- [3]=>test.php
- )
- */
你可以像這樣獲得多個文件:
- 以下為引用的內(nèi)容:
- //getallphpfilesANDtxtfiles
- $files=glob(‘*.{php,txt}’,GLOB_BRACE);
- print_r($files);
- /*outputlookslike:
- Array
- (
- [0]=>phptest.php
- [1]=>pi.php
- [2]=>post_output.php
- [3]=>test.php
- [4]=>log.txt
- [5]=>test.txt
- )
- */
請注意,這些文件其實是可以返回一個路徑,這取決于查詢條件:
- 以下為引用的內(nèi)容:
- $files=glob(‘../images/a*.jpg’);
- print_r($files);
- /*outputlookslike:
- Array
- (
- [0]=>../images/apple.jpg
- [1]=>../images/art.jpg
- )
- */
如果你想獲得每個文件的完整路徑,你可以調(diào)用realpath()函數(shù):
- 以下為引用的內(nèi)容:
- $files=glob(‘../images/a*.jpg’);
- //appliesthefunctiontoeacharrayelement
- $files=array_map(‘realpath’,$files);
- print_r($files);
- /*outputlookslike:
- Array
- (
- [0]=>C:\wamp\www\images\apple.jpg
- [1]=>C:\wamp\www\images\art.jpg
- )
- */
#p#
3、內(nèi)存使用信息
通過偵測腳本的內(nèi)存使用情況,有利于代碼的優(yōu)化。PHP提供了一個垃圾收集器和一個非常復(fù)雜的內(nèi)存管理器。腳本執(zhí)行時所使用的內(nèi)存量,有升有跌。為了得到當(dāng)前的內(nèi)存使用情況,我們可以使用memory_get_usage()函數(shù)。如果需要獲得任意時間點的***內(nèi)存使用量,則可以使用memory_limit()函數(shù)。
- 以下為引用的內(nèi)容:
- echo“Initial:“.memory_get_usage().”bytes\n”;
- /*prints
- Initial:361400bytes
- */
- //let’suseupsomememory
- for($i=0;$i<100000;$i++){
- $array[]=md5($i);
- }
- //let'sremovehalfofthearray
- for($i=0;$i<100000;$i++){
- unset($array[$i]);
- }
- echo"Final:".memory_get_usage()."bytes\n";
- /*prints
- Final:885912bytes
- */
- echo"Peak:".memory_get_peak_usage()."bytes\n";
- /*prints
- Peak:13687072bytes
- */
4、CPU使用信息
為此,我們要利用getrusage()函數(shù)。請記住這個函數(shù)不適用于Windows平臺。
- 以下為引用的內(nèi)容:
- 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
- )
這可能看起來有點神秘,除非你已經(jīng)有系統(tǒng)管理員權(quán)限。以下是每個值的具體說明(你不需要記住這些):
- 以下為引用的內(nèi)容:
- ru_oublock:blockoutputoperations
- ru_inblock:blockinputoperations
- ru_msgsnd:messagessent
- ru_msgrcv:messagesreceived
- ru_maxrss:maximumresidentsetsize
- ru_ixrss:integralsharedmemorysize
- ru_idrss:integralunshareddatasize
- ru_minflt:pagereclaims
- ru_majflt:pagefaults
- ru_nsignals:signalsreceived
- ru_nvcsw:voluntarycontextswitches
- ru_nivcsw:involuntarycontextswitches
- ru_nswap:swaps
- ru_utime.tv_usec:usertimeused(microseconds)
- ru_utime.tv_sec:usertimeused(seconds)
- ru_stime.tv_usec:systemtimeused(microseconds)
- ru_stime.tv_sec:systemtimeused(seconds)
要知道腳本消耗多少CPU功率,我們需要看看‘usertime’和’systemtime’兩個參數(shù)的值。秒和微秒部分默認(rèn)是單獨提供的。你可以除以100萬微秒,并加上秒的參數(shù)值,得到一個十進制的總秒數(shù)。讓我們來看一個例子:
- 以下為引用的內(nèi)容:
- //sleepfor3seconds(non-busy)
- sleep(3);
- $data=getrusage();
- echo“Usertime:“.
- ($data['ru_utime.tv_sec']+
- $data['ru_utime.tv_usec']/1000000);
- echo“Systemtime:“.
- ($data['ru_stime.tv_sec']+
- $data['ru_stime.tv_usec']/1000000);
- /*prints
- Usertime:0.011552
- Systemtime:0
- */
盡管腳本運行用了大約3秒鐘,CPU使用率卻非常非常低。因為在睡眠運行的過程中,該腳本實際上不消耗CPU資源。還有許多其他的任務(wù),可能需要一段時間,但不占用類似等待磁盤操作等CPU時間。因此正如你所看到的,CPU使用率和運行時間的實際長度并不總是相同的。下面是一個例子:
- 以下為引用的內(nèi)容:
- //loop10milliontimes(busy)
- for($i=0;$i<10000000;$i++){
- }
- $data=getrusage();
- echo"Usertime:".
- ($data['ru_utime.tv_sec']+
- $data['ru_utime.tv_usec']/1000000);
- echo"Systemtime:".
- ($data['ru_stime.tv_sec']+
- $data['ru_stime.tv_usec']/1000000);
- /*prints
- Usertime:1.424592
- Systemtime:0.004204
- */
這花了大約1.4秒的CPU時間,但幾乎都是用戶時間,因為沒有系統(tǒng)調(diào)用。系統(tǒng)時間是指花費在執(zhí)行程序的系統(tǒng)調(diào)用時的CPU開銷。下面是一個例子:
- 以下為引用的內(nèi)容:
- $start=microtime(true);
- //keepcallingmicrotimeforabout3seconds
- while(microtime(true)-$start<3){
- }
- $data=getrusage();
- echo"Usertime:".
- ($data['ru_utime.tv_sec']+
- $data['ru_utime.tv_usec']/1000000);
- echo"Systemtime:".
- ($data['ru_stime.tv_sec']+
- $data['ru_stime.tv_usec']/1000000);
- /*prints
- Usertime:1.088171
- Systemtime:1.675315
- */
現(xiàn)在我們有相當(dāng)多的系統(tǒng)時間占用。這是因為腳本多次調(diào)用microtime()函數(shù),該函數(shù)需要向操作系統(tǒng)發(fā)出請求,以獲取所需時間。你也可能會注意到運行時間加起來不到3秒。這是因為有可能在服務(wù)器上同時存在其他進程,并且腳本沒有100%使用CPU的整個3秒持續(xù)時間。
#p#
5、魔術(shù)常量
PHP提供了獲取當(dāng)前行號(__LINE__)、文件路徑(__FILE__)、目錄路徑(__DIR__)、函數(shù)名(__FUNCTION__)、類名(__CLASS__)、方法名(__METHOD__)和命名空間(__NAMESPACE__)等有用的魔術(shù)常量。在這篇文章中不作一一介紹,但是我將告訴你一些用例。當(dāng)包含其他腳本文件時,使用__FILE__常量(或者使用PHP5.3新具有的__DIR__常量):
- 以下為引用的內(nèi)容:
- //thisisrelativetotheloadedscript'spath
- //itmaycauseproblemswhenrunningscriptsfromdifferentdirectories
- require_once('config/database.php');
- //thisisalwaysrelativetothisfile'spath
- //nomatterwhereitwasincludedfrom
- require_once(dirname(__FILE__).'/config/database.php');
使用__LINE__使得調(diào)試更為輕松。你可以跟蹤到具體行號。
- 以下為引用的內(nèi)容:
- //somecode
- //...
- my_debug("somedebugmessage",__LINE__);
- /*prints
- Line4:somedebugmessage
- */
- //somemorecode
- //...
- my_debug("anotherdebugmessage",__LINE__);
- /*prints
- Line11:anotherdebugmessage
- */
- functionmy_debug($msg,$line){
- echo"Line$line:$msg
6、生成唯一標(biāo)識符
某些場景下,可能需要生成一個唯一的字符串。我看到很多人使用md5()函數(shù),即使它并不完全意味著這個目的:
- 以下為引用的內(nèi)容:
- //generateuniquestring
- echomd5(time().mt_rand(1,1000000));
- ThereisactuallyaPHPfunctionnameduniqid()thatismeanttobeusedforthis.
- //generateuniquestring
- echouniqid();
- /*prints
- 4bd67c947233e
- */
- //generateanotheruniquestring
- echouniqid();
- /*prints
- 4bd67c9472340
- */
你可能會注意到,盡管字符串是唯一的,前幾個字符卻是類似的,這是因為生成的字符串與服務(wù)器時間相關(guān)。但實際上也存在友好的一方面,由于每個新生成的ID會按字母順序排列,這樣排序就變得很簡單。為了減少重復(fù)的概率,你可以傳遞一個前綴,或第二個參數(shù)來增加熵。
- 以下為引用的內(nèi)容:
- //withprefix
- echouniqid('foo_');
- /*prints
- foo_4bd67d6cd8b8f
- */
- //withmoreentropy
- echouniqid('',true);
- /*prints
- 4bd67d6cd8b926.12135106
- */
- //both
- echouniqid('bar_',true);
- /*prints
- bar_4bd67da367b650.43684647
- */
這個函數(shù)將產(chǎn)生比md5()更短的字符串,能節(jié)省一些空間。
7、序列化
你有沒有遇到過需要在數(shù)據(jù)庫或文本文件存儲一個復(fù)雜變量的情況?你可能沒能想出一個格式化字符串并轉(zhuǎn)換成數(shù)組或?qū)ο蟮暮梅椒?,PHP已經(jīng)為你準(zhǔn)備好此功能。有兩種序列化變量的流行方法。下面是一個例子,使用serialize()和unserialize()函數(shù)。以下為引用的內(nèi)容:
- //acomplexarray
- $myvar=array(
- 'hello',
- 42,
- array(1,'two'),
- 'apple'
- );
- //converttoastring
- $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";}
- */
- //youcanreproducetheoriginalvariable
- $newvar=unserialize($string);
- print_r($newvar);
- /*prints
- Array
- (
- [0]=>hello
- [1]=>42
- [2]=>Array
- (
- [0]=>1
- [1]=>two
- )
- [3]=>apple
- )
- */
這是原生的PHP序列化方法。然而,由于JSON近年來大受歡迎,PHP5.2中已經(jīng)加入了對JSON格式的支持?,F(xiàn)在你可以使用json_encode()和json_decode()函數(shù),以下為引用的內(nèi)容:
- //acomplexarray
- $myvar=array(
- ‘hello’,
- 42,
- array(1,’two’),
- ‘apple’
- );
- //converttoastring
- $string=json_encode($myvar);
- echo$string;
- /*prints
- ["hello",42,[1,"two"],”apple”]
- */
- //youcanreproducetheoriginalvariable
- $newvar=json_decode($string);
- print_r($newvar);
- /*prints
- Array
- (
- [0]=>hello
- [1]=>42
- [2]=>Array
- (
- [0]=>1
- [1]=>two
- )
- [3]=>apple
- )
- */
這將更為行之有效,尤其與JavaScript等許多其他語言兼容。然而對于復(fù)雜的對象,某些信息可能會丟失。
文章轉(zhuǎn)自PHP之家,
原文地址:http://www.phpzj.org/php_0002.html
【編輯推薦】
- PHP開發(fā)者不可不知的五件事
- PHP開發(fā)人員容易忽略的幾點精華
- FirePHP:像Firebug那樣調(diào)試你的PHP代碼
- PHP應(yīng)用JSON技巧講解
- 解讀PHP冒泡排序技巧