九個PHP中很有用的功能

下面是九個PHP中很有用的功能,不知道你用過了嗎? 1. 函數的任意數目的參數 你可能知道PHP允許你定義一個默認參數的函數。但你可能並不知道PHP還允許你定義一個完全任意的參數的函數 下面是一個示例向你展示了默認參數的函數: 查看源代碼 打印幫助 01 // 兩個默認參數的函數 02 function foo($arg1 = '', $arg2 = '') { 03 04 echo "arg1: $arg1/n"; 05 echo "arg2: $arg2/n"; 06 07 } 08 09 foo('hello','world'); 10 /* 輸出: 11 arg1: hello 12 arg2: world 13 */ 14 15 foo(); 16 /* 輸出: 17 arg1: 18 arg2: 19 */ 現在我們來看一看一個不定參數的函數,其使用到了?func_get_args()方法: 查看源代碼 打印幫助 01 // 是的,形參列表爲空 02 function foo() { 03 04 // 取得所有的傳入參數的數組 05 $args = func_get_args(); 06 07 foreach ($args as $k => $v) { 08 echo "arg".($k+1).": $v/n"; 09 } 10 11 } 12 13 foo(); 14 /* 什麼也不會輸出 */ 15 16 foo('hello'); 17 /* 輸出 18 arg1: hello 19 */ 20 21 foo('hello', 'world', 'again'); 22 /* 輸出 23 arg1: hello 24 arg2: world 25 arg3: again 26 */ 2. 使用 Glob() 查找文件 很多PHP的函數都有一個比較長的自解釋的函數名,但是,當你看到?glob() 的時候,你可能並不知道這個函數是用來幹什麼的,除非你對它已經很熟悉了。 你可以認爲這個函數就好?scandir() 一樣,其可以用來查找文件。 查看源代碼 打印幫助 01 // 取得所有的後綴爲PHP的文件 02 $files = glob('*.php'); 03 04 print_r($files); 05 /* 輸出: 06 Array 07 ( 08 [0] => phptest.php 09 [1] => pi.php 10 [2] => post_output.php 11 [3] => test.php 12 ) 13 */ 你還可以查找多種後綴名 查看源代碼 打印幫助 01 // 取PHP文件和TXT文件 02 $files = glob('*.{php,txt}', GLOB_BRACE); 03 04 print_r($files); 05 /* 輸出: 06 Array 07 ( 08 [0] => phptest.php 09 [1] => pi.php 10 [2] => post_output.php 11 [3] => test.php 12 [4] => log.txt 13 [5] => test.txt 14 ) 15 */ 你還可以加上路徑: 查看源代碼 打印幫助 01 $files = glob('../images/a*.jpg'); 02 03 print_r($files); 04 /* 輸出: 05 Array 06 ( 07 [0] => ../images/apple.jpg 08 [1] => ../images/art.jpg 09 ) 10 */ 如果你想得到絕對路徑,你可以調用?realpath() 函數: 查看源代碼 打印幫助 01 $files = glob('../images/a*.jpg'); 02 03 // applies the function to each array element 04 $files = array_map('realpath',$files); 05 06 print_r($files); 07 /* output looks like: 08 Array 09 ( 10 [0] => C:/wamp/www/images/apple.jpg 11 [1] => C:/wamp/www/images/art.jpg 12 ) 13 */ 3. 內存使用信息 觀察你程序的內存使用能夠讓你更好的優化你的代碼。 PHP 是有垃圾回收機制的,而且有一套很複雜的內存管理機制。你可以知道你的腳本所使用的內存情況。要知道當前內存使用情況,你可以使用?memory_get_usage() 函數,如果你想知道使用內存的峯值,你可以調用memory_get_peak_usage() 函數。 查看源代碼 打印幫助 01 echo "Initial: ".memory_get_usage()." bytes /n"; 02 /* 輸出 03 Initial: 361400 bytes 04 */ 05 06 // 使用內存 07 for ($i = 0; $i < 100000; $i++) { 08 $array []= md5($i); 09 } 10 11 // 刪除一半的內存 12 for ($i = 0; $i < 100000; $i++) { 13 unset($array[$i]); 14 } 15 16 echo "Final: ".memory_get_usage()." bytes /n"; 17 /* prints 18 Final: 885912 bytes 19 */ 20 21 echo "Peak: ".memory_get_peak_usage()." bytes /n"; 22 /* 輸出峯值 23 Peak: 13687072 bytes 24 */ 4. CPU使用信息 使用?getrusage() 函數可以讓你知道CPU的使用情況。注意,這個功能在Windows下不可用。 查看源代碼 打印幫助 01 print_r(getrusage()); 02 /* 輸出 03 Array 04 ( 05 [ru_oublock] => 0 06 [ru_inblock] => 0 07 [ru_msgsnd] => 2 08 [ru_msgrcv] => 3 09 [ru_maxrss] => 12692 10 [ru_ixrss] => 764 11 [ru_idrss] => 3864 12 [ru_minflt] => 94 13 [ru_majflt] => 0 14 [ru_nsignals] => 1 15 [ru_nvcsw] => 67 16 [ru_nivcsw] => 4 17 [ru_nswap] => 0 18 [ru_utime.tv_usec] => 0 19 [ru_utime.tv_sec] => 0 20 [ru_stime.tv_usec] => 6269 21 [ru_stime.tv_sec] => 0 22 ) 23 24 */ 這個結構看上出很晦澀,除非你對CPU很瞭解。下面一些解釋: * ru_oublock: 塊輸出操作 * ru_inblock: 塊輸入操作 * ru_msgsnd: 發送的message * ru_msgrcv: 收到的message * ru_maxrss: 最大駐留集大小 * ru_ixrss: 全部共享內存大小 * ru_idrss:全部非共享內存大小 * ru_minflt: 頁回收 * ru_majflt: 頁失效 * ru_nsignals: 收到的信號 * ru_nvcsw: 主動上下文切換 * ru_nivcsw: 被動上下文切換 * ru_nswap: 交換區 * ru_utime.tv_usec: 用戶態時間 (microseconds) * ru_utime.tv_sec: 用戶態時間(seconds) * ru_stime.tv_usec: 系統內核時間 (microseconds) * ru_stime.tv_sec: 系統內核時間?(seconds) 要看到你的腳本消耗了多少CPU,我們需要看看“用戶態的時間”和“系統內核時間”的值。秒和微秒部分是分別提供的,您可以把微秒值除以100萬,並把它添加到秒的值後,可以得到有小數部分的秒數。 查看源代碼 打印幫助 01 // sleep for 3 seconds (non-busy) 02 sleep(3); 03 04 $data = getrusage(); 05 echo "User time: ". 06 ($data['ru_utime.tv_sec'] + 07 $data['ru_utime.tv_usec'] / 1000000); 08 echo "System time: ". 09 ($data['ru_stime.tv_sec'] + 10 $data['ru_stime.tv_usec'] / 1000000); 11 12 /* 輸出 13 User time: 0.011552 14 System time: 0 15 */ sleep是不佔用系統時間的,我們可以來看下面的一個例子: 查看源代碼 打印幫助 01 // loop 10 million times (busy) 02 for($i=0;$i<10000000;$i++) { 03 04 } 05 06 $data = getrusage(); 07 echo "User time: ". 08 ($data['ru_utime.tv_sec'] + 09 $data['ru_utime.tv_usec'] / 1000000); 10 echo "System time: ". 11 ($data['ru_stime.tv_sec'] + 12 $data['ru_stime.tv_usec'] / 1000000); 13 14 /* 輸出 15 User time: 1.424592 16 System time: 0.004204 17 */ 這花了大約14秒的CPU時間,幾乎所有的都是用戶的時間,因爲沒有系統調用。 系統時間是CPU花費在系統調用上的上執行內核指令的時間。下面是一個例子: 查看源代碼 打印幫助 01 $start = microtime(true); 02 // keep calling microtime for about 3 seconds 03 while(microtime(true) - $start < 3) { 04 05 } 06 07 $data = getrusage(); 08 echo "User time: ". 09 ($data['ru_utime.tv_sec'] + 10 $data['ru_utime.tv_usec'] / 1000000); 11 echo "System time: ". 12 ($data['ru_stime.tv_sec'] + 13 $data['ru_stime.tv_usec'] / 1000000); 14 15 /* prints 16 User time: 1.088171 17 System time: 1.675315 18 */ 我們可以看到上面這個例子更耗CPU。 5. 系統常量 PHP 提供非常有用的系統常量 可以讓你得到當前的行號 (__LINE__),文件 (__FILE__),目錄 (__DIR__),函數名 (__FUNCTION__),類名(__CLASS__),方法名(__METHOD__) 和名字空間 (__NAMESPACE__),很像C語言。 我們可以以爲這些東西主要是用於調試,當也不一定,比如我們可以在include其它文件的時候使用?__FILE__ (當然,你也可以在 PHP 5.3以後使用 __DIR__ ),下面是一個例子。 查看源代碼 打印幫助 1 // this is relative to the loaded script's path 2 // it may cause problems when running scripts from different directories 3 require_once('config/database.php'); 4 5 // this is always relative to this file's path 6 // no matter where it was included from 7 require_once(dirname(__FILE__) . '/config/database.php'); 下面是使用 __LINE__ 來輸出一些debug的信息,這樣有助於你調試程序: 查看源代碼 打印幫助 01 // some code 02 // ... 03 my_debug("some debug message", __LINE__); 04 /* 輸出 05 Line 4: some debug message 06 */ 07 08 // some more code 09 // ... 10 my_debug("another debug message", __LINE__); 11 /* 輸出 12 Line 11: another debug message 13 */ 14 15 function my_debug($msg, $line) { 16 echo "Line $line: $msg/n"; 17 } 6.生成唯一的ID 有很多人使用 md5() 來生成一個唯一的ID,如下所示: 查看源代碼 打印幫助 1 // generate unique string 2 echo md5(time() . mt_rand(1,1000000)); 其實,PHP中有一個叫?uniqid() 的函數是專門用來幹這個的: 查看源代碼 打印幫助 01 // generate unique string 02 echo uniqid(); 03 /* 輸出 04 4bd67c947233e 05 */ 06 07 // generate another unique string 08 echo uniqid(); 09 /* 輸出 10 4bd67c9472340 11 */ 可能你會注意到生成出來的ID前幾位是一樣的,這是因爲生成器依賴於系統的時間,這其實是一個非常不錯的功能,因爲你是很容易爲你的這些ID排序的。這點MD5是做不到的。 你還可以加上前綴避免重名: 查看源代碼 打印幫助 01 // 前綴 02 echo uniqid('foo_'); 03 /* 輸出 04 foo_4bd67d6cd8b8f 05 */ 06 07 // 有更多的熵 08 echo uniqid('',true); 09 /* 輸出 10 4bd67d6cd8b926.12135106 11 */ 12 13 // 都有 14 echo uniqid('bar_',true); 15 /* 輸出 16 bar_4bd67da367b650.43684647 17 */ 而且,生成出來的ID會比MD5生成的要短,這會讓你節省很多空間。 7. 序列化 你是否會把一個比較複雜的數據結構存到數據庫或是文件中?你並不需要自己去寫自己的算法。PHP早已爲你做好了,其提供了兩個函數:?serialize() 和 unserialize(): 查看源代碼 打印幫助 01 // 一個複雜的數組 02 $myvar = array( 03 'hello', 04 42, 05 array(1,'two'), 06 'apple' 07 ); 08 09 // 序列化 10 $string = serialize($myvar); 11 12 echo $string; 13 /* 輸出 14 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";} 15 */ 16 17 // 反序例化 18 $newvar = unserialize($string); 19 20 print_r($newvar); 21 /* 輸出 22 Array 23 ( 24 [0] => hello 25 [1] => 42 26 [2] => Array 27 ( 28 [0] => 1 29 [1] => two 30 ) 31 32 [3] => apple 33 ) 34 */ 這是PHP的原生函數,然而在今天JSON越來越流行,所以在PHP5.2以後,PHP開始支持JSON,你可以使用 json_encode() 和 json_decode() 函數 查看源代碼 打印幫助 01 // a complex array 02 $myvar = array( 03 'hello', 04 42, 05 array(1,'two'), 06 'apple' 07 ); 08 09 // convert to a string 10 $string = json_encode($myvar); 11 12 echo $string; 13 /* prints 14 ["hello",42,[1,"two"],"apple"] 15 */ 16 17 // you can reproduce the original variable 18 $newvar = json_decode($string); 19 20 print_r($newvar); 21 /* prints 22 Array 23 ( 24 [0] => hello 25 [1] => 42 26 [2] => Array 27 ( 28 [0] => 1 29 [1] => two 30 ) 31 32 [3] => apple 33 ) 34 */ 這看起來更爲緊湊一些了,而且還兼容於Javascript和其它語言。但是對於一些非常複雜的數據結構,可能會造成數據丟失。 8. 字符串壓縮 當我們說到壓縮,我們可能會想到文件壓縮,其實,字符串也是可以壓縮的。PHP提供了?gzcompress() 和 gzuncompress() 函數: 查看源代碼 打印幫助 01 $string = 02 "Lorem ipsum dolor sit amet, consectetur 03 adipiscing elit. Nunc ut elit id mi ultricies 04 adipiscing. Nulla facilisi. Praesent pulvinar, 05 sapien vel feugiat vestibulum, nulla dui pretium orci, 06 non ultricies elit lacus quis ante. Lorem ipsum dolor 07 sit amet, consectetur adipiscing elit. Aliquam 08 pretium ullamcorper urna quis iaculis. Etiam ac massa 09 sed turpis tempor luctus. Curabitur sed nibh eu elit 10 mollis congue. Praesent ipsum diam, consectetur vitae 11 ornare a, aliquam a nunc. In id magna pellentesque 12 tellus posuere adipiscing. Sed non mi metus, at lacinia 13 augue. Sed magna nisi, ornare in mollis in, mollis 14 sed nunc. Etiam at justo in leo congue mollis. 15 Nullam in neque eget metus hendrerit scelerisque 16 eu non enim. Ut malesuada lacus eu nulla bibendum 17 id euismod urna sodales. "; 18 19 $compressed = gzcompress($string); 20 21 echo "Original size: ". strlen($string)."/n"; 22 /* 輸出原始大小 23 Original size: 800 24 */ 25 26 echo "Compressed size: ". strlen($compressed)."/n"; 27 /* 輸出壓縮後的大小 28 Compressed size: 418 29 */ 30 31 // 解壓縮 32 $original = gzuncompress($compressed); 幾乎有50% 壓縮比率。同時,你還可以使用?gzencode() 和 gzdecode() 函數來壓縮,只不用其用了不同的壓縮算法。 9. 註冊停止函數 有一個函數叫做?register_shutdown_function(),可以讓你在整個腳本停時前運行代碼。讓我們看下面的一個示例: 查看源代碼 打印幫助 01 // capture the start time 02 $start_time = microtime(true); 03 04 // do some stuff 05 // ... 06 07 // display how long the script took 08 echo "execution took: ". 09 (microtime(true) - $start_time). 10 " seconds."; 上面這個示例只不過是用來計算某個函數運行的時間。然後,如果你在函數中間調用?exit() 函數,那麼你的最後的代碼將不會被運行到。並且,如果該腳本在瀏覽器終止(用戶按停止按鈕),其也無法被運行。 而當我們使用了register_shutdown_function()後,你的程序就算是在腳本被停止後也會被運行: 查看源代碼 打印幫助 01 $start_time = microtime(true); 02 03 register_shutdown_function('my_shutdown'); 04 05 // do some stuff 06 // ... 07 08 function my_shutdown() { 09 global $start_time; 10 11 echo "execution took: ". 12 (microtime(true) - $start_time). 13 " seconds."; 14 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章