九個你需要知道的PHP函數和功能

來源:互聯網
上載者:User
9個你需要知道的PHP函數和功能
即使使用 PHP 多年,有些功能和特點我們也未必發現或未被充分利用,一旦被我們發現,就會發現它們非常有用。然而,並不是所有的人都已經從頭至尾詳讀過 PHP 的手冊和功能參考!

1. 函數與任意數量的參數
您可能已經知道,PHP 允許我們定義選擇性參數的函數。但也有完全允許任意數量的函數參數方法。

首先,下面這個例子只是選擇性參數:

view sourceprint?01 // function with 2 optional arguments

02 function foo($arg1 = '', $arg2 = '') {

03 echo "arg1: $arg1\n";

04 echo "arg2: $arg2\n";

05 }

06 foo('hello','world');

07 /* prints:

08 arg1: hello

09 arg2: world

10 */

11 foo();

12 /* prints:

13 arg1:

14 arg2:

15 */

現在,讓我們看看如何可以建立一個函數接受任何數量的參數。這一次,我們要利用 func_get_args() 函數:

view sourceprint?01 // yes, the argument list can be empty

02 function foo() {

03 // returns an array of all passed arguments

04 $args = func_get_args();

05 foreach ($args as $k => $v) {

06 echo "arg".($k+1).": $v\n";

07 }

08 }

09 foo();

10 /* prints nothing */

11 foo('hello');

12 /* prints

13 arg1: hello

14 */

15 foo('hello', 'world', 'again');

16 /* prints

17 arg1: hello

18 arg2: world

19 arg3: again

20 */

2. 使用 Glob() 函數來尋找檔案
許多 PHP 內建函數有非常長的命名。然而,它可能會很難說明是什麼作用的函數,如果不使用 Glob() 來做,除非你已經非常熟悉這個函數。

它更像是 scandir() 函數加強型版本。它可以讓您通過使用模式搜尋檔案。

view sourceprint?01 // get all php files

02 $files = glob('*.php');

03 print_r($files);

04 /* output looks like:

05 Array

06 (

07 [0] => phptest.php

08 [1] => pi.php

09 [2] => post_output.php

10 [3] => test.php

11 )

12 */

這樣你可以獲得多個檔案類型:

view sourceprint?01 // get all php files AND txt files

02 $files = glob('*.{php,txt}', GLOB_BRACE);

03 print_r($files);

04 /* output looks like:

05 Array

06 (

07 [0] => phptest.php

08 [1] => pi.php

09 [2] => post_output.php

10 [3] => test.php

11 [4] => log.txt

12 [5] => test.txt

13 )

14 */

請注意,這些檔案其實是可以返回一個路徑的,根據你的查詢。

view sourceprint?1 $files = glob('../images/a*.jpg');

2 print_r($files);

3 /* output looks like:

4 Array

5 (

6 [0] => ../images/apple.jpg

7 [1] => ../images/art.jpg

8 )

9 */

如果你想獲得每個檔案的完整路徑,你可以調用 realpath() 函數來返回。

view sourceprint?01 $files = glob('../images/a*.jpg');

02 // applies the function to each array element

03 $files = array_map('realpath',$files);

04 print_r($files);

05 /* output looks like:

06 Array

07 (

08 [0] => C:\wamp\www\images\apple.jpg

09 [1] => C:\wamp\www\images\art.jpg

10 )

11 */

3. 記憶體使用量資訊
通過觀察你的指令碼記憶體使用方式,你就可以將你的代碼進行針對性最佳化。

PHP 有一個垃圾收集器和一個相當複雜的記憶體管理器。當你的指令碼開始就開始正式使用記憶體。也會根據指令碼的執行情況,記憶體使用量量會上升也會下降。為了得到當前記憶體使用量情況,我們就可以使用 memory_get_usage() 函數。並可以在任何時候得到記憶體使用量的最高點,下面就是使用 memory_get_usage() 函數的例子。

view sourceprint?01 echo "Initial: ".memory_get_usage()." bytes \n";

02 /* prints

03 Initial: 361400 bytes

04 */

05 // let's use up some memory

06 for ($i = 0; $i < 100000; $i++) {

07 $array []= md5($i);

08 }

09 // let's remove half of the array

10 for ($i = 0; $i < 100000; $i++) {

11 unset($array[$i]);

12 }

13 echo "Final: ".memory_get_usage()." bytes \n";

14 /* prints

15 Final: 885912 bytes

16 */

17 echo "Peak: ".memory_get_peak_usage()." bytes \n";

18 /* prints

19 Peak: 13687072 bytes

20 */

4. CPU 的使用資訊
為此,我們就要利用 getrusage() 函數。請記住,這個函數不能應用於 windows 平台。

view sourceprint?01 print_r(getrusage());

02 /* prints

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

這看起來蠻神秘的,有些艱澀難懂,除非你已經有過系統管理員的經驗,以下是每個值的介紹(或許你並不需要記住這些):

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 萬毫秒的值,並將其換算成秒的值,將它當做一個十進位數的總秒數。

讓我們看一個例子:

view sourceprint?01 // sleep for 3 seconds (non-busy)

02 sleep(3);

03 $data = getrusage();

04 echo "User time: ".

05 ($data['ru_utime.tv_sec'] +

06 $data['ru_utime.tv_usec'] / 1000000);

07 echo "System time: ".

08 ($data['ru_stime.tv_sec'] +

09 $data['ru_stime.tv_usec'] / 1000000);

10 /* prints

11 User time: 0.011552

12 System time: 0

13 */

雖然指令碼大約花了 3 秒鐘的時間來運行, CPU 的使用率還是非常非常低的。因為 sleep 工作,指令碼實際上並沒有消耗 CPU 資源。當然還有其他的任務可能真正需要等待時間,但千萬不能用磁碟的讀取寫入操作來等待 CPU 時間。所以你可以發現, CPU 使用率和運行時的實際長度並不是總是一樣的。

下面是另外一個例子。

view sourceprint?01 // loop 10 million times (busy)

02 for($i=0;$i< 10000000;$i++) {

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

12 User time: 1.424592

13 System time: 0.004204

14 */

這花了大約 1.4 秒的 CPU 時間。幾乎所有這些都是由使用者操作所用的時間,系統並沒有被調用。

系統時間是劃分時間的 CPU 上執行的程式的代表的核心系統調用時間。(誰有更簡明扼要的描述?help!)下面是一個例子:

view sourceprint?01 $start = microtime(true);

02 // keep calling microtime for about 3 seconds

03 while(microtime(true) - $start < 3) {

04 }

05 $data = getrusage();

06 echo "User time: ".

07 ($data['ru_utime.tv_sec'] +

08 $data['ru_utime.tv_usec'] / 1000000);

09 echo "System time: ".

10 ($data['ru_stime.tv_sec'] +

11 $data['ru_stime.tv_usec'] / 1000000);

12 /* prints

13 User time: 1.088171

14 System time: 1.675315

15 */

5. 魔術常量
PHP 提供了擷取當前行號的方法 (__LINE__),擷取檔案路徑方法(__FILE__),目錄(__DIR__),函數名(__FUNCTTION__),類名(__CLASS__),方法名(__METHOD__),和命名空間(__NAMESPACE__)。以上就是常用的魔術常量。恐怕我們最常用的就只有 (__FILE__) 了。

Rikku 不打算全部進行說明,但會說幾個用例。

當然包括了其他的指令碼,這是個不錯的主意。((__DIR__)需要 PHP 5.3 以上版本):

view sourceprint?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 // this is always relative to this file's path

5 // no matter where it was included from

6 require_once(dirname(__FILE__) . '/config/database.php');

使用 __LINE__ 讓調試更加容易,你可以跟蹤行號:

view sourceprint?01 // some code

02 // ...

03 my_debug("some debug message", __LINE__);

04 /* prints

05 Line 4: some debug message

06 */

07 // some more code

08 // ...

09 my_debug("another debug message", __LINE__);

10 /* prints

11 Line 11: another debug message

12 */

13 function my_debug($msg, $line) {

14 echo "Line $line: $msg\n";

15 }

6. 產生唯一的ID
有些情況下,您需要產生一股唯一的字串。我看到很多人會用這個 md5() 函數,即使他並不完全用於此目的的存在:

view sourceprint?1 // generate unique string

2 echo md5(time() . mt_rand(1,1000000));

其實有個專門的 PHP 函數,名為 uniqid() 就是為了這個目的而存在的:

view sourceprint?01 // generate unique string

02 echo uniqid();

03 /* prints

04 4bd67c947233e

05 */

06 // generate another unique string

07 echo uniqid();

08 /* prints

09 4bd67c9472340

10 */

您可能會注意到,即使是唯一的字串,他們的前幾個字元很相似。這是因為產生的字串是關聯到伺服器時間的。設實際上有一個非常好的副作用,因為每個新產生的 ID 將在產生後按字母順序排列,這樣也省去了我們排序的邏輯動作。

為了減少重複的幾率,你可以傳遞一個首碼,或在第二個參數來增加。

view sourceprint?01 // with prefix

02 echo uniqid('foo_');

03 /* prints

04 foo_4bd67d6cd8b8f

05 */

06 // with more entropy

07 echo uniqid('',true);

08 /* prints

09 4bd67d6cd8b926.12135106

10 */

11 // both

12 echo uniqid('bar_',true);

13 /* prints

14 bar_4bd67da367b650.43684647

15 */

此功能將會產生比 md5() 產生的字串更短,這也將節省您的空間。

7. 序列化
你有沒有需要儲存在資料庫中複雜的變數或者大文字檔?那你有沒有拿出一個解決方案,花式轉換成格式化的字串數組或對象的?別擔心,PHP 已經為我們準備好了這個功能。

有兩種序列化的方法,下面是一個例子,它使用 serialize() 進行序列化和 unserialize() 進行解除序列化:

view sourceprint?01 // a complex array

02 $myvar = array(

03 'hello',

04 42,

05 array(1,'two'),

06 'apple'

07 );

08 // convert to a string

09 $string = serialize($myvar);

10 echo $string;

11 /* prints

12 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";}

13 */

14 // you can reproduce the original variable

15 $newvar = unserialize($string);

16 print_r($newvar);

17 /* prints

18 Array

19 (

20 [0] => hello

21 [1] => 42

22 [2] => Array

23 (

24 [0] => 1

25 [1] => two

26 )

27 [3] => apple

28 )

29 */

這是原生態的 PHP 序列化方法。然而,由於 JSON 近年來已經大受歡迎,PHP 5.2 中也決定添加對它們的支援。現在你可以使用 json_encode() 和 json_decode() 函數來完成這項工作:

view sourceprint?01 // a complex array

02 $myvar = array(

03 'hello',

04 42,

05 array(1,'two'),

06 'apple'

07 );

08 // convert to a string

09 $string = json_encode($myvar);

10 echo $string;

11 /* prints

12 ["hello",42,[1,"two"],"apple"]

13 */

14 // you can reproduce the original variable

15 $newvar = json_decode($string);

16 print_r($newvar);

17 /* prints

18 Array

19 (

20 [0] => hello

21 [1] => 42

22 [2] => Array

23 (

24 [0] => 1

25 [1] => two

26 )

27 [3] => apple

28 )

29 */

這麼做看起來會更加緊湊。當然它對其他語言如 javascript 相容性也是最好的。然而,您需要注意的是:對於某些複雜的對象,某些資訊會無故丟失!

8. 壓縮字串
在談到壓縮時,我們通常會想到一些檔案,如 zip 檔案。它可以在 PHP 中壓縮長字串,並且不涉及任何封存檔案。

在下面的例子中,我們要利用 gzcompress() 和 gzuncompress() 函數:

view sourceprint?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 $compressed = gzcompress($string);

19 echo "Original size: ". strlen($string)."\n";

20 /* prints

21 Original size: 800

22 */

23 echo "Compressed size: ". strlen($compressed)."\n";

24 /* prints

25 Compressed size: 418

26 */

27 // getting it back

28 $original = gzuncompress($compressed);

我們能夠壓縮近 50% 。另外 gzencode() 和 gzdecode() 可以達成類似的結果,但通過的是不同的壓縮演算法。

9. register_shutdown_function
有一個函數叫 register_shutdown_function(),可以讓你在擁有執行一些代碼許可權之前,完成指令碼的運行。

試想一下,你想捕捉到你指令碼執行至結束時一些基準的統計資料,如一共用了多少時間來執行:

view sourceprint?1 // capture the start time

2 $start_time = microtime(true);

3 // do some stuff

4 // ...

5 // display how long the script took

6 echo "execution took: ".

7 (microtime(true) - $start_time).

8 " seconds.";

起初覺得這些似乎是微不足道的。你只要添加代碼放在底部,它運行指令碼之前完成。不過,在指令碼程式其中你調用了 exit() 函數,那麼該段代碼將不被執行。此外,如果有一個致命的錯誤,或者該指令碼由使用者終止(就是按瀏覽器上面的停止按鈕),再次重新整理頁面也無法被運行。

當您使用 register_shutdown_function(),你的代碼將沒有理由被迫停止:

view sourceprint?01 $start_time = microtime(true);

02 register_shutdown_function('my_shutdown');

03 // do some stuff

04 // ...

05 function my_shutdown() {

06 global $start_time;

07 echo "execution took: ".

08 (microtime(true) - $start_time).

09 " seconds.";

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.