php易錯筆記-流程控制,函式

Maxiye發表於2019-02-16

流程控制

PHP 提供了一些流程控制的替代語法,包括 ifwhileforforeachswitch。替代語法的基本形式是把左花括號({)換成冒號(:),把右花括號(})分別換成 endif;,endwhile;,endfor;,endforeach; 以及 endswitch;。
Note: 不支援在同一個控制塊內混合使用兩種語法。

特別注意:

switch 和第一個 case 之間的任何輸出(含空格)將導致語法錯誤。例如,這樣是無效的:

<?php switch ($foo): ?>
    <?php case 1: ?>
    ...
<?php endswitch ?>

而這樣是有效的,因為 switch 之後的換行符被認為是結束標記 ?> 的一部分,所以在 switchcase 之間不能有任何輸出:

<?php switch ($foo): ?>
<?php case 1: ?>
    ...
<?php endswitch ?>

if/else

Note: 必須要注意的是 elseif 與 else if 只有在使用花括號的情況下才認為是完全相同。如果用冒號來定義 if/elseif 條件,那就不能用兩個單詞的 else if,否則 PHP 會產生解析錯誤。

<?php

/* 不正確的使用方法: */
if($a > $b):
    echo $a." is greater than ".$b;
else if($a == $b): // 將無法編譯
    echo "The above line causes a parse error.";
endif;


/* 正確的使用方法: */
if($a > $b):
    echo $a." is greater than ".$b;
elseif($a == $b): // 注意使用了一個單詞的 elseif
    echo $a." equals ".$b;
else:
    echo $a." is neither greater than or equal to ".$b;
endif;

?>

for

for 迴圈是 PHP 中最複雜的迴圈結構。它的行為和 C 語言的相似。 for 迴圈的語法是:

for (expr1; expr2; expr3)
    statement

第一個表示式(expr1)在迴圈開始前無條件求值(並執行)一次。

expr2每次迴圈開始前求值。如果值為 TRUE,則繼續迴圈,執行巢狀的迴圈語句。如果值為 FALSE,則終止迴圈。

expr3每次迴圈之後被求值(並執行)。

每個表示式都可以為空或包括逗號分隔的多個表示式
表示式 expr2 中,所有用逗號分隔的表示式都會計算,但只取最後一個結果expr2 為空意味著將無限迴圈下去(和 C 一樣,PHP 暗中認為其值為 TRUE)。這可能不像想象中那樣沒有用,因為經常會希望用有條件的 break 語句來結束迴圈而不是用 for 的表示式真值判斷。

考慮以下的例子,它們都顯示數字 1 到 10:

/* example 2 */    
for ($i = 1; ; $i++) {
    if ($i > 10) {
        break;
    }
    echo $i;
}

/* example 3 */    
$i = 1;
for (;;) {
    if ($i > 10) {
        break;
    }
    echo $i;
    $i++;
}

/* example 4 */    
for ($i = 1, $j = 0; $i <= 10; $j += $i, print $i, $i++);

/* example */
$people = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for($i = 0, $size = count($people); $i < $size; ++$i)
{
    print $people[$i];
}

excel中可以使用:

<?php
for($col = `R`; $col != `AD`; $col++) {
    echo $col.` `;
}

//returns: R S T U V W X Y Z AA AB AC

//Take note that you can`t use $col < `AD`. It only works with !=
//Very convenient when working with excel columns.
?>

foreach

在 $value 之前加上 & 來修改陣列的元素。此方法將以引用賦值而不是拷貝一個值(最後切記unset()變數,否則可能出現一些意料之外的結果)。

<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
    $value = $value * 2;
}
// $arr is now array(2, 4, 6, 8)
unset($value); // 最後取消掉引用
?>

以下的程式碼功能完全相同:

<?php
$arr = array("one", "two", "three");
reset($arr);
while (list(, $value) = each($arr)) {
    echo "Value: $value<br>
";
}

foreach ($arr as $value) {
    echo "Value: $value<br />
";
}
?>

以下程式碼功能也完全相同:

<?php
$arr = array("one", "two", "three");
reset($arr);
while (list($key, $value) = each($arr)) {
    echo "Key: $key; Value: $value<br />
";
}

foreach ($arr as $key => $value) {
    echo "Key: $key; Value: $value<br />
";
}
?>

list() 給巢狀的陣列解包

(PHP 5 >= 5.5.0, PHP 7)
PHP 5.5 增添了遍歷一個陣列的陣列的功能並且把巢狀的陣列解包到迴圈變數中,只需將 list() 作為值提供。

<?php
$array = [
    [1, 2],
    [3, 4],
];    
foreach ($array as list($a, $b)) {
    // $a contains the first element of the nested array,
    // and $b contains the second element.
    echo "A: $a; B: $b
";
}
?>

以上例程會輸出:

A: 1; B: 2
A: 3; B: 4

break

break 結束當前 forforeachwhiledo-while 或者 switch 結構的執行。

break 可以接受一個可選的數字引數來決定跳出幾重迴圈

<?php
$i = 0;
while (++$i) {
    switch ($i) {
    case 5:
        echo "At 5<br />
";
        break 1;  /* 只退出 switch. */
    case 10:
        echo "At 10; quitting<br />
";
        break 2;  /* 退出 switch 和 while 迴圈 */
    default:
        break;
    }
}
?>
版本 說明
5.4.0 break 0; 不再合法。這在之前的版本被解析為 break 1;。
5.4.0 取消變數作為引數傳遞(例如 $num = 2; break $num;)。

A break statement that is in the outer part of a program (e.g. not in a control loop) will end the script.

<?php 
echo "hello";
if (true) break;
echo " world";
?>

will only show “hello”

continue

continue 在迴圈結構用用來跳過本次迴圈中剩餘的程式碼並在條件求值為真時開始執行下一次迴圈。
Note: 注意在 PHP 中 switch 語句被認為是可以使用 continue 的一種迴圈結構。

continue 接受一個可選的數字引數來決定跳過幾重迴圈到迴圈結尾。預設值是 1,即跳到當前迴圈末尾。

<?php
$i = 0;
while ($i++ < 5) {
    echo "Outer<br />
";
    while (1) {
        echo "Middle<br />
";
        while (1) {
            echo "Inner<br />
";
            continue 3;
        }
        echo "This never gets output.<br />
";
    }
    echo "Neither does this.<br />
";
}
?>
版本 說明
5.4.0 continue 0; 不再合法。這在之前的版本被解析為 continue 1;。
5.4.0 取消變數作為引數傳遞(例如 $num = 2; continue $num;)。
<?php

    for( $i = 0; $i < 3; ++ $i )
    {
        echo ` [`, $i, `] `;
        switch( $i )
        {
            case 0: echo `zero`; break;
            case 1: echo `one` ; XXXX;
            case 2: echo `two` ; break;
        }
        echo ` <` , $i, `> `;
    }

?>

For XXXX I filled in

- continue 1//[0] zero <0>  [1] one <1>  [2] two <2>
- continue 2//[0] zero <0>  [1] one [2] two <2>
- break 1//[0] zero <0>  [1] one <1>  [2] two <2>
- break 2//[0] zero <0>  [1] one

switch

Note: 注意和其它語言不同,continue 語句作用到 switch 上的作用類似於 break。如果在迴圈中有一個 switch 並希望 continue 到外層迴圈中的下一輪迴圈,用 continue 2

Note: 注意 switch/case 作的是鬆散比較

<?php
$a = 0;

if(++$a == 3) echo 3;
elseif(++$a == 2) echo 2;
elseif(++$a == 1) echo 1;
else echo "No match!";

// Outputs: 2

$a = 0;

switch(++$a) {
    case 3: echo 3; break;
    case 2: echo 2; break;
    case 1: echo 1; break;
    default: echo "No match!"; break;
}

// Outputs: 1
?>

declare

(PHP 4, PHP 5, PHP 7)
declare 結構用來設定一段程式碼的執行指令。declare 的語法和其它流程控制結構相似:

declare (directive)
    statement

directive 部分允許設定 declare 程式碼段的行為。目前只認識兩個指令:ticks 以及 encoding(PHP 5.3.0+)。

declare 程式碼段中的 statement 部分將被執行——怎樣執行以及執行中有什麼副作用出現取決於 directive 中設定的指令。

declare 結構也可用於全域性範圍,影響到其後的所有程式碼(但如果有 declare 結構的檔案被其它檔案包含,則對包含它的父檔案不起作用)。

<?php
// these are the same:

// you can use this:
declare(ticks=1) {
    // entire script here
}

// or you can use this:
declare(ticks=1);
// entire script here
?>

Ticks

Tick(時鐘週期)是一個在 declare 程式碼段中直譯器每執行 N 條可計時的低階語句就會發生的事件。N 的值是在 declare 中的 directive 部分用 ticks=N 來指定的。

不是所有語句都可計時。通常條件表示式和參數列達式都不可計時

在每個 tick 中出現的事件是由 register_tick_function() 來指定的。更多細節見下面的例子。注意每個 tick 中可以出現多個事件。

Example #1 Tick 的用法示例

<?php

declare(ticks=1);

// A function called on each tick event
function tick_handler()
{
    echo "tick_handler() called
";
}

register_tick_function(`tick_handler`);

$a = 1;

if ($a > 0) {
    $a += 2;
    print($a);
}
/*
tick_handler() called
tick_handler() called
tick_handler() called
3tick_handler() called
 */
?>

Example #2 Ticks 的用法示例

<?php

function tick_handler()
{
  echo "tick_handler() called
";
}

$a = 1;
tick_handler();

if ($a > 0) {
    $a += 2;
    tick_handler();
    print($a);
    tick_handler();
}
tick_handler();

?>

參見 register_tick_function() 和 unregister_tick_function()。

Encoding

可以用 encoding 指令來對每段指令碼指定其編碼方式。

Example #3 對指令碼指定編碼方式

<?php
declare(encoding=`ISO-8859-1`);
// code here
?>

當和名稱空間結合起來時 declare 的唯一合法語法是 declare(encoding=`…`);,其中 … 是編碼的值。而
declare(encoding=`…`) {} 將在與名稱空間結合時產生解析錯誤。 在 PHP 5.3 中除非在編譯時指定了
–enable-zend-multibyte,否則 declare 中的 encoding 值會被忽略。

注意除非用 phpinfo(),否則 PHP 不會顯示出是否在編譯時指定了 –enable-zend-multibyte。

參見 zend.script_encoding。

require/include(建議配合魔術常量使用)

requireinclude 幾乎完全一樣,除了處理失敗的方式不同之外。require 在出錯時產生 E_COMPILE_ERROR 級別的錯誤。換句話說將導致指令碼中止而 include 只產生警告(E_WARNING),指令碼會繼續執行。

1.被包含檔案先按引數給出的路徑尋找,如果沒有給出目錄(只有檔名)時則按照 include_path 指定的目錄尋找。如果在 include_path 下沒找到該檔案則 include 最後才在呼叫指令碼檔案所在的目錄當前工作目錄下尋找。
2.如果定義了路徑——不管是絕對路徑(在 Windows 下以碟符或者 開頭,在 Unix/Linux 下以 / 開頭)還是當前目錄的相對路徑(以 . 或者 .. 開頭)——include_path 都會被完全忽略。例如一個檔案以 ../ 開頭,則解析器會在當前目錄的父目錄下尋找該檔案。

作用域:

1.當一個檔案被包含時,其中所包含的程式碼繼承了 include 所在行的變數範圍。從該處開始,呼叫檔案在該行處可用的任何變數在被呼叫的檔案中也都可用。
2.不過所有在包含檔案中定義的函式和類都具有全域性作用域(引入了一個類stdClass,如果要例項化則使用 new stdClass)。

當一個檔案被包含時,語法解析器在目標檔案的開頭脫離 PHP 模式並進入 HTML 模式,到檔案結尾處恢復。由於此原因,目標檔案中需要作為 PHP 程式碼執行的任何程式碼都必須被包括在有效的 PHP 起始和結束標記之中。

返回值:

失敗時 include 返回 FALSE 並且發出警告。成功的包含則返回 1,除非在包含檔案中另外給出了返回值。可以在被包括的檔案中使用 return 語句來終止該檔案中程式的執行並返回撥用它的指令碼。同樣也可以從被包含的檔案中返回值。可以像普通函式一樣獲得 include 呼叫的返回值。

file.php
<?php 
$a = [`aa`];
 ?>

php.php
<?php 
return [`aa`];
 ?>

<?php 
if (false) {
    require `file`;
    require(`file.php`);
}
//include `file`;//Warning
var_export(include(`file.php`));echo "
";
if (true) {
    echo require `file.php`, "
";
    var_dump(@include `file`);echo "
";
    var_dump(require `php.php`);echo "
";
    var_dump((include(`php.php`)) == [`aa`]);echo "
";//注意括號,等同(include `php.php`) == [`aa`]
    var_dump(include(`php.php`) == [`aa`]);echo "
";//等同於include((`php.php`) == [`aa`])
    require `file`;
}
echo `End`;
/*
1
1
bool(false)

array(1) {
  [0]=>
  string(2) "aa"
}

bool(true)

PHP Warning:  include(): Filename cannot be empty in D:php	est	est.php on line 13

Warning: include(): Filename cannot be empty in D:php	est	est.php on line 13
PHP Warning:  include(): Failed opening `` for inclusion (include_path=`.;C:phppear`) in D:php	est	est.php on line 13

Warning: include(): Failed opening `` for inclusion (include_path=`.;C:phppear`) in D:php	est	est.php on line 13
bool(false)

PHP Warning:  require(file): failed to open stream: No such file or directory in D:php	est	est.php on line 14

Warning: require(file): failed to open stream: No such file or directory in D:php	est	est.php on line 14
PHP Fatal error:  require(): Failed opening required `file` (include_path=`.;C:phppear`) in D:php	est	est.php on line 14

Fatal error: require(): Failed opening required `file` (include_path=`.;C:phppear`) in D:php	est	est.php on line 14
 */
 ?>

函式:

如果在包含檔案中定義有函式,這些函式不管是在 return 之前還是之後定義的,都可以獨立在主檔案中使用。如果檔案被包含兩次,PHP 5 發出致命錯誤因為函式已經被定義,但是 PHP 4 不會對在 return 之後定義的函式報錯。推薦使用 include_once 而不是檢查檔案是否已包含並在包含檔案中有條件返回。

另一個將 PHP 檔案“包含”到一個變數中的方法是用輸出控制函式結合 include 來捕獲其輸出,例如:

Example #6 使用輸出緩衝來將 PHP 檔案包含入一個字串

<?php
$string = get_include_contents(`somefile.php`);

function get_include_contents($filename) {
    if (is_file($filename)) {
        ob_start();
        include $filename;
        $contents = ob_get_contents();
        ob_end_clean();
        return $contents;
    }
    return false;
}

?>

Note: 因為是一個語言構造器而不是一個函式,不能被 可變函式(如:$var()) 呼叫。

require_once/include_once

require_once/include_once 語句和 require/include 語句完全相同,唯一區別是 PHP 會檢查該檔案是否已經被包含過,如果是則不會再次包含。

例項(php 7.0.12):

<?php 
var_dump(include_once `file.php`); // int(1)
var_dump(include_once `file.php`); // bool(true)
 ?>

goto

goto 操作符可以用來跳轉到程式中的另一位置。該目標位置可以用目標名稱加上冒號來標記,而跳轉指令是 goto 之後接上目標位置的標記。

PHP 中的 goto 有一定限制,目標位置只能位於同一個檔案和作用域,也就是說無法跳出一個函式或類方法,也無法跳入到另一個函式。也無法跳入到任何迴圈或者 switch 結構中。可以跳出迴圈或者 switch,通常的用法是用 goto 代替多層的 break

Example #2 goto 跳出迴圈示例

<?php
for($i=0,$j=50; $i<100; $i++) {
  while($j--) {
    if($j==17) goto end; 
  }  
}
echo "i = $i";
end:
echo `j hit 17`;
?>

以上例程會輸出:

//j hit 17

Example #3 以下寫法無效

<?php
goto loop;
for($i=0,$j=50; $i<100; $i++) {
  while($j--) {
    loop:
  }
}
echo "$i = $i";
?>

以上例程會輸出:

Fatal error: `goto` into loop or switch statement is disallowed in
script on line 2

特別的例子:

Remember if you are not a fan of wild labels hanging around you are free to use braces in this construct creating a slightly cleaner look. 
Labels also are always executed and do not need to be called to have their associated code block ran. A purposeless example is below.
<?php 

$headers = Array(`subject`, `bcc`, `to`, `cc`, `date`, `sender`); 
$position = 0; 

hIterator: { 

    $c = 0; 
    echo $headers[$position] . PHP_EOL; 

    cIterator: { 
        echo ` ` . $headers[$position][$c] . PHP_EOL; 

        if(!isset($headers[$position][++$c])) { 
            goto cIteratorExit; 
        } 
        goto cIterator; 
    } 

    cIteratorExit: { 
        if(isset($headers[++$position])) { 
            goto hIterator; 
        } 
    } 
} 
?>

函式

使用者自定義函式

函式無需在呼叫之前被定義,除非是下面兩個例子中函式是有條件被定義時。

當一個函式是有條件被定義時,必須在呼叫函式之前定義

Example #2 有條件的函式

<?php    
$makefoo = true;

/* 不能在此處呼叫foo()函式,
   因為它還不存在,但可以呼叫bar()函式。*/    
bar();

if ($makefoo) {
  function foo()
  {
    echo "I don`t exist until program execution reaches me.
";
  }
}    
/* 現在可以安全呼叫函式 foo()了,
   因為 $makefoo 值為真 */    
if ($makefoo) foo();

function bar()
{
  echo "I exist immediately upon program start.
";
}

?>

PHP 中的所有函式和類都具有全域性作用域,可以定義在一個函式之內而在之外呼叫,反之亦然。

PHP 不支援函式過載,也不可能取消定義或者重定義已宣告的函式

<?php
function foo() {
  function bar() {
    echo "I don`t exist until foo() is called.
";
  }
}

/* 現在還不能呼叫bar()函式,因為它還不存在 */
foo();

/* 現在可以呼叫bar()函式了,因為foo()函式
   的執行使得bar()函式變為已定義的函式 */    
bar();

?>

函式的引數

PHP 支援按值傳遞引數(預設),通過引用傳遞引數以及預設引數。也支援可變長度引數列表

引用傳遞:在函式定義(而不是使用時)中該引數的前面加上符號 &function xxx(&$a, $b) {}
預設引數:預設值必須是常量表示式(標量,array,NULL),不能是諸如變數類成員,或者函式呼叫等。
型別宣告(型別提示)
型別宣告允許函式在呼叫時要求引數為特定型別。 如果給出的值型別不對,那麼將會產生一個錯誤: 在PHP 5中,這將是一個可恢復的致命錯誤,而在PHP 7中將會丟擲一個TypeError異常

為了指定一個型別宣告,型別應該加到引數名前。這個宣告可以通過將引數的預設值設為NULL來實現允許傳遞NULL

Type Description Minimum PHP version
Class/interface name The parameter must be an instanceof the given class or interface name. PHP 5.0.0
self The parameter must be an instanceof the same class as the one the method is defined on. This can only be used on class and instance methods. PHP 5.0.0
array The parameter must be an array. PHP 5.1.0
callable The parameter must be a valid callable. PHP 5.4.0
bool The parameter must be a boolean value. PHP 7.0.0
float The parameter must be a floating point number. PHP 7.0.0
int The parameter must be an integer. PHP 7.0.0
string The parameter must be a string. PHP 7.0.0

注意:型別提示只能是以上表格中的型別(單詞),例如bool不能寫作boolean(boolean會被當作class或interface解析)。

型別提示:

<?php
 function test(boolean $param) {}
 test(true);
 ?>

以上例程會輸出:

Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of boolean, boolean given, called in - on line 1 and defined in -:1

嚴格型別:使用 declare 語句和strict_types 宣告來啟用嚴格模式(如declare(strict_types=1);)。
可變數量的引數列表
PHP 在使用者自定義函式中支援可變數量的引數列表。在 PHP 5.6 及以上的版本中,由 ... 語法實現(類似於js);在 PHP 5.5 及更早版本中,使用函式 func_num_args()func_get_arg(),和 func_get_args()

...既可以用於定義可變引數列表,也可以用來提供引數解包

Example #13 使用 ... 定義可變引數 in PHP 5.6+

<?php
function sum(...$numbers) {
    $acc = 0;
    foreach ($numbers as $n) {
        $acc += $n;
    }
    return $acc;
}

echo sum(1, 2, 3, 4);//10
?>

Example #14 使用 ... 提供引數

<?php
function add($a, $b) {
    return $a + $b;
}

echo add(...[1, 2])."
";//3

$a = [1, 2];
echo add(...$a);//3
?>

Example #15 部分可變引數以及可變引數列表的型別提示

<?php
function total_intervals($unit, DateInterval ...$intervals) {
    $time = 0;
    foreach ($intervals as $interval) {
        $time += $interval->$unit;
    }
    return $time;
}

$a = new DateInterval(`P1D`);
$b = new DateInterval(`P2D`);
echo total_intervals(`d`, $a, $b).` days`;//3 days

// This will fail, since null isn`t a DateInterval object.
echo total_intervals(`d`, null);
//Catchable fatal error: Argument 2 passed to total_intervals() must be an instance of DateInterval, null given, called in - on line 14 and defined in - on line 2
?>

在php 5.5以及之前版本中使用可變引數

<?php
function sum() {
    $acc = 0;
    foreach (func_get_args() as $n) {
        $acc += $n;
    }
    return $acc;
}

echo sum(1, 2, 3, 4);//10
?>

返回值

如果省略了 return,則返回值為 NULL。

Example #1 return 的使用

<?php
function square($num) {
    $sum = $num * $num;
}
function square2($num) {
    $sum = $num * $num;
    return;
}
var_dump(square(4));   // NULL
var_dump(square2(4));   // NULL
?>

從函式返回一個引用,必須在函式宣告和指派返回值給一個變數時都使用引用運算子 &

Example #3 從函式返回一個引用

<?php
function &returns_reference()
{
    return $someref;
}

$newref =& returns_reference();
?>

可變函式

PHP 支援可變函式的概念。這意味著如果一個變數名後有圓括號,PHP 將尋找與變數的值同名的函式,並且嘗試執行它。可變函式可以用來實現包括回撥函式,函式表在內的一些用途。

可變函式不能用於例如 echoprintunset()isset()empty()includerequire 以及類似的語言結構。需要使用自己的包裝函式來將這些結構用作可變函式。

當呼叫靜態方法時,函式呼叫要比靜態屬性優先

Example #3 Variable 方法和靜態屬性示例

<?php
class Foo
{
    static $variable = `static property`;
    static function Variable() {
        echo `Method Variable called`;
    }
}

echo Foo::$variable; // This prints `static property`. It does need a $variable in this scope.
$variable = "Variable";
Foo::$variable();  // This calls $foo->Variable() reading $variable in this scope.

?>

As of PHP 5.4.0, you can call any callable stored in a variable.

Example #4 Complex callables

<?php
class Foo
{
    static function bar()
    {
        echo "bar
";
    }
    function baz()
    {
        echo "baz
";
    }
}

$func = array("Foo", "bar");
$func(); // prints "bar"
$func = array(new Foo, "baz");
$func(); // prints "baz"
$func = "Foo::bar";
$func(); // prints "bar" as of PHP 7.0.0; prior, it raised a fatal error
?>

匿名函式

匿名函式(Anonymous functions),也叫閉包函式(closures),允許 臨時建立一個沒有指定名稱的函式。最經常用作回撥函式(callback)引數的值。當然,也有其它應用的情況。

匿名函式目前是通過 Closure 類來實現的。

閉包可以從父作用域中繼承變數。 任何此類變數都應該用 use 語言結構傳遞進去。 PHP 7.1 起,不能傳入此類變數: superglobals、 $this 或者和引數重名。

Example #3 從父作用域繼承變數(傳值傳引用

<?php
$message = `hello`;

// 沒有 "use"
$example = function () {
    var_dump($message);
};
echo $example();
//Notice: Undefined variable: message in /example.php on line 6
//NULL

// 繼承 $message
$example = function () use ($message) {
    var_dump($message);
};
echo $example();//string(5) "hello"

$message = `world`;
echo $example();//string(5) "hello"

// Reset message
$message = `hello`;

$example = function () use (&$message) {
    var_dump($message);
};
echo $example();//string(5) "hello"

$message = `world`;
echo $example();//string(5) "world"

// Closures can also accept regular arguments
$example = function ($arg) use ($message) {
    var_dump($arg . ` ` . $message);
};
$example("hello");//string(11) "hello world"
?>

閉包中 $this 的繫結

<?php

class Test
{
    public function testing()
    {
        return function() {
            var_dump($this);
        };
    }
    public function testing2()
    {
        return static function() {
            var_dump($this);
        };
    }
}

$object = new Test;
$function = $object->testing();
$function();
$object->testing2()();
?>

以上例程會輸出(PHP 5.4+):

object(Test)#1 (0) {
}
PHP Notice:  Undefined variable: this in D:php	est	est.php on line 13

Notice: Undefined variable: this in D:php	est	est.php on line 13
NULL

而在PHP 5.3中:

PHP Notice:  Undefined variable: this in D:php	est	est.php on line 7

Notice: Undefined variable: this in D:php	est	est.php on line 7
NULL

PHP Parse error:  syntax error, unexpected T_FUNCTION, expecting T_PAAMAYIM_NEKUDOTAYIM in D:php	est	est.php on line 12

Parse error: syntax error, unexpected T_FUNCTION, expecting T_PAAMAYIM_NEKUDOTAYIM in D:php	est	est.php on line 12

Note: 可以在閉包中使用 func_num_args(),func_get_arg() 和 func_get_args()。

函式處理 函式

相關文章