即便你已经使用PHP多年,也难免会偶尔发现一些之前从未了解过的函数和功能。其中有些非常实用,却未得到充分利用。毕竟,不是每个人都会逐页通读PHP手册和函数参考文档!下面就来为大家介绍9个重要且实用的PHP函数和功能。
1. 支持任意参数数目的函数
在PHP中,我们都知道可以定义带有可选参数的函数,比如:
1 2 3 4 5 6 7 8 9 10 11 12 13
| function foo($arg1 = '', $arg2 = '') { echo "arg1: $arg1\n"; echo "arg2: $arg2\n"; } foo('hello', 'world');
foo();
|
不过,PHP还提供了一种方法,允许定义能接受任意数目的函数参数。这时候就要用到func_get_args()
函数,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function foo() { $args = func_get_args(); foreach ($args as $k => $v) { echo "arg". ($k + 1). ": $v\n"; } } foo();
foo('hello');
foo('hello', 'world', 'again');
|
2. 使用glob()
查找文件
PHP中有不少函数名称很长且具有描述性,但glob()
函数可能让人不太容易猜出它的功能,除非你经常使用它。可以把glob()
看作是比scandir()
更强大的函数,它能够按照特定模式搜索文件。
获取所有PHP文件:
1 2 3 4 5 6 7 8 9 10 11
| $files = glob('*.php'); print_r($files);
|
获取多种类型的文件,例如PHP文件和TXT文件:
1 2 3 4 5 6 7 8 9 10 11 12 13
| $files = glob('*.{php,txt}', GLOB_BRACE); print_r($files);
|
glob()
函数返回的文件路径取决于查询条件,例如:
1 2 3 4 5 6 7 8
| $files = glob('../images/a*.jpg'); print_r($files);
|
如果想要获取每个文件的完整路径,可以结合realpath()
函数使用:
1 2 3 4 5 6 7 8 9 10
| $files = glob('../images/a*.jpg');
$files = array_map('realpath', $files); print_r($files);
|
3. 内存使用信息
监测脚本的内存使用情况,对优化代码很有帮助。PHP拥有垃圾收集器和复杂的内存管理器,脚本执行过程中内存使用量会有所波动。要获取当前内存使用情况,可以使用memory_get_usage()
函数;若想知道脚本在执行过程中的最高内存使用量,则可以使用memory_get_peak_usage()
函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| echo "Initial: ". memory_get_usage(). " bytes \n";
for ($i = 0; $i < 100000; $i++) { $array [] = md5($i); }
for ($i = 0; $i < 100000; $i++) { unset($array[$i]); } echo "Final: ". memory_get_usage(). " bytes \n";
echo "Peak: ". memory_get_peak_usage(). " bytes \n";
|
4. CPU使用信息
在PHP中,可以利用getrusage()
函数获取CPU使用信息,但需要注意的是,该函数不适用于Windows平台。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| print_r(getrusage());
|
上述输出结果可能看起来有些晦涩,下面为大家解释每个值的含义(无需强行记忆):
ru_oublock
:块输出操作数
ru_inblock
:块输入操作数
ru_msgsnd
:发送的消息数
ru_msgrcv
:接收的消息数
ru_maxrss
:最大驻留集大小
ru_ixrss
:共享内存大小
ru_idrss
:非共享数据大小
ru_minflt
:页面回收次数
ru_majflt
:页面错误次数
ru_nsignals
:接收的信号数
ru_nvcsw
:自愿上下文切换次数
ru_nivcsw
:非自愿上下文切换次数
ru_nswap
:交换次数
ru_utime.tv_usec
:用户态使用的微秒数
ru_utime.tv_sec
:用户态使用的秒数
ru_stime.tv_usec
:系统态使用的微秒数
ru_stime.tv_sec
:系统态使用的秒数
要了解脚本消耗的CPU功率,主要关注user time
(用户时间)和system time
(系统时间)这两个参数。这两个参数的值默认分别以秒和微秒为单位提供,我们可以将微秒部分除以100万,再加上秒数部分,得到总的十进制秒数。
例如:
1 2 3 4 5 6 7 8 9 10 11 12
| 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);
|
尽管脚本运行了约3秒,但CPU使用率非常低,因为睡眠过程中脚本实际上不消耗CPU资源。还有很多任务可能耗时较长,但不会占用CPU时间,比如等待磁盘操作。
再看一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 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);
|
这个循环大约消耗了1.4秒的CPU时间,且几乎都是用户时间,因为没有系统调用。系统时间是指执行程序系统调用时的CPU开销。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| $start = microtime(true);
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);
|
在这个例子中,系统时间占用较多,这是因为脚本多次调用microtime()
函数,该函数需要向操作系统请求获取时间。你可能还会发现运行时间加起来不到3秒,这是因为服务器上可能同时存在其他进程,脚本并没有100%占用CPU的3秒持续时间。
5. 魔术常量
PHP提供了一系列非常有用的魔术常量,如当前行号__LINE__
、文件路径__FILE__
、目录路径__DIR__
、函数名__FUNCTION__
、类名__CLASS__
、方法名__METHOD__
和命名空间__NAMESPACE__
等。这里不一一详细介绍,主要分享一些它们的使用场景。
在包含其他脚本文件时,可以使用__FILE__
常量(或者PHP 5.3新增的__DIR__
常量):
1 2 3 4
| require_once('config/database.php');
require_once(dirname(__FILE__) . '/config/database.php');
|
__LINE__
常量在调试时非常有用,它可以帮助我们追踪到具体的代码行号。
1 2 3 4 5 6 7 8 9 10 11
|
my_debug("some debug message", __LINE__);
my_debug("another debug message", __LINE__);
function my_debug($msg, $line) { echo "Line $line: $msg"; }
|
6. 生成唯一标识符
在某些场景下,我们需要生成唯一的字符串。很多人会使用md5()
函数,但它并非专门用于此目的。实际上,PHP提供了uniqid()
函数来生成唯一标识符:
1 2 3 4 5 6 7 8
| echo md5(time(). mt_rand(1,1000000));
echo uniqid();
echo uniqid();
|
可以发现,uniqid()
生成的字符串虽然是唯一的,但前几个字符相似,这是因为生成的字符串与服务器时间相关。不过,这也有好处,新生成的ID会按字母顺序排列,方便排序。如果想进一步降低重复概率,可以传递一个前缀,或者设置第二个参数增加熵值。
1 2 3 4 5 6 7 8 9
| echo uniqid('foo_');
echo uniqid('',true);
echo uniqid('bar_',true);
|
相比md5()
函数,uniqid()
生成的字符串更短,能节省一定的空间。
7. 序列化
在开发过程中,我们可能会遇到需要在数据库或文本文件中存储复杂变量的情况。PHP提供了序列化变量的功能,有两种常用的方法。
使用serialize()
和unserialize()
函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| $myvar = array( 'hello', 42, array(1, 'two'), 'apple' );
$string = serialize($myvar); echo $string;
$newvar = unserialize($string); print_r($newvar);
|
随着JSON的广泛应用,PHP 5.2及以上版本加入了对JSON格式的支持,可以使用json_encode()
和json_decode()
函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| $myvar = array( 'hello', 42, array(1, 'two'), 'apple' );
$string = json_encode($myvar); echo $string;
$newvar = json_decode($string); print_r($newvar);
|
使用JSON序列化的方式更高效,并且与JavaScript等多种语言兼容。不过,对于复杂对象,可能会丢失一些信息。