PHP的真正威力源自于它的函数

分类:PHP | 作者:凹凸曼 | 发表于2011/10/10

 PHP的真正威力源自于它的函数,但有些PHP函数并没有得到充分的利用,也并不是所有人都会从头到尾一页一页地阅读手册和函数参考,这里将向您介绍这些实用的函数和功能。

  1、任意参数数目的函数

  你可能已经知道,PHP允许定义可选参数的函数。但也有完全允许任意数目的函数参数的方法。以下是可选参数的例子:

以下为引用的内容:   
 

//functionwith2optionalarguments
functionfoo($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,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
*/

2、使用Glob()查找文件

  许多PHP函数具有长描述性的名称。然而可能会很难说出glob()函数能做的事情,除非你已经通过多次使用并熟悉了它。可以把它看作是比scandir()函数更强大的版本,可以按照某种模式搜索文件。

以下为引用的内容:   
 

//getallphpfiles
$files=glob(‘*.php’);   

print_r($files);
/*outputlookslike:
Array
(
[0]=>phptest.php
[1]=>pi.php
[2]=>post_output.php
[3]=>test.php
)
*/

  你可以像这样获得多个文件:

以下为引用的内容:   
 

//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
)
*/

  请注意,这些文件其实是可以返回一个路径,这取决于查询条件:

以下为引用的内容:  
 

$files=glob(‘../images/a*.jpg’);  
 
print_r($files);  
/*outputlookslike:  
Array  
(  
[0]=>../images/apple.jpg  
[1]=>../images/art.jpg  
)  
*/ 

 请注意,这些文件其实是可以返回一个路径,这取决于查询条件:

以下为引用的内容:  
 

$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  
)  
*/ 

3、内存使用信息

  通过侦测脚本的内存使用情况,有利于代码的优化。PHP提供了一个垃圾收集器和一个非常复杂的内存管理器。脚本执行时所使用的内存量,有升有跌。为了得到当前的内存使用情况,我们可以使用memory_get_usage()函数。如果需要获得任意时间点的最高内存使用量,则可以使用memory_limit()函数。

以下为引用的内容:  
 

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()函数。请记住这个函数不适用于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: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’两个参数的值。秒和微秒部分默认是单独提供的。你可以除以100万微秒,并加上秒的参数值,得到一个十进制的总秒数。让我们来看一个例子:

以下为引用的内容:  
 

//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资源。还有许多其他的任务,可能需要一段时间,但不占用类似等待磁盘操作等CPU时间。因此正如你所看到的,CPU使用率和运行时间的实际长度并不总是相同的。下面是一个例子:

以下为引用的内容:  
 

//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时间,但几乎都是用户时间,因为没有系统调用。系统时间是指花费在执行程序的系统调用时的CPU开销。下面是一个例子:

以下为引用的内容:  
 

$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  
*/ 

  现在我们有相当多的系统时间占用。这是因为脚本多次调用microtime()函数,该函数需要向操作系统发出请求,以获取所需时间。你也可能会注意到运行时间加起来不到3秒。这是因为有可能在服务器上同时存在其他进程,并且脚本没有100%使用CPU的整个3秒持续时间。

5、魔术常量

  PHP提供了获取当前行号(__LINE__)、文件路径(__FILE__)、目录路径(__DIR__)、函数名(__FUNCTION__)、类名(__CLASS__)、方法名(__METHOD__)和命名空间(__NAMESPACE__)等有用的魔术常量。在这篇文章中不作一一介绍,但是我将告诉你一些用例。当包含其他脚本文件时,使用__FILE__常量(或者使用PHP5.3新具有的__DIR__常量):

以下为引用的内容:  
 

//thisisrelativetotheloadedscript'spath  
//itmaycauseproblemswhenrunningscriptsfromdifferentdirectories  
require_once('config/database.php');  
 
//thisisalwaysrelativetothisfile'spath  
//nomatterwhereitwasincludedfrom  
require_once(dirname(__FILE__).'/config/database.php');

  使用__LINE__使得调试更为轻松。你可以跟踪到具体行号。

以下为引用的内容:

//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、生成唯一标识符

  某些场景下,可能需要生成一个唯一的字符串。我看到很多人使用md5()函数,即使它并不完全意味着这个目的:

以下为引用的内容:  
 

//generateuniquestring  
echomd5(time().mt_rand(1,1000000));  
ThereisactuallyaPHPfunctionnameduniqid()thatismeanttobeusedforthis.  
 
//generateuniquestring  
echouniqid();  
/*prints  
4bd67c947233e  
*/  
 
//generateanotheruniquestring  
echouniqid();  
/*prints  
4bd67c9472340  
*/ 

  你可能会注意到,尽管字符串是唯一的,前几个字符却是类似的,这是因为生成的字符串与服务器时间相关。但实际上也存在友好的一方面,由于每个新生成的ID会按字母顺序排列,这样排序就变得很简单。为了减少重复的概率,你可以传递一个前缀,或第二个参数来增加熵。

以下为引用的内容:  
 

//withprefix  
echouniqid('foo_');  
/*prints  
foo_4bd67d6cd8b8f  
*/  
 
//withmoreentropy  
echouniqid('',true);  
/*prints  
4bd67d6cd8b926.12135106  
*/  
 
//both  
echouniqid('bar_',true);  
/*prints  
bar_4bd67da367b650.43684647  
*/ 

  这个函数将产生比md5()更短的字符串,能节省一些空间。

7、序列化

  你有没有遇到过需要在数据库或文本文件存储一个复杂变量的情况?你可能没能想出一个格式化字符串并转换成数组或对象的好方法,PHP已经为你准备好此功能。有两种序列化变量的流行方法。下面是一个例子,使用serialize()和unserialize()函数。以下为引用的内容:

//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中已经加入了对JSON格式的支持。现在你可以使用json_encode()和json_decode()函数,以下为引用的内容:

//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等许多其他语言兼容。然而对于复杂的对象,某些信息可能会丢失。

这篇文章在清理文档是发觉的,我觉得写的好,回味一下还是不错的,遗憾的是忘记了,是谁写的了!

本文出自 “凹凸曼” 博客,请务必保留此出处 http://www.apoyl.com/?p=1198

Tag:

日志信息 »

该日志于2011-10-10 11:46由 凹凸曼 发表在PHP分类下, 你可以发表评论。除了可以将这个日志以保留源地址及作者的情况下引用到你的网站或博客,还可以通过RSS 2.0订阅这个日志的所有评论。

目前盖楼 (0)层:

发表评论 »

« »