PHP 提供了一些流程控制的替代語法,包括if
,while
,for
,foreach
和switch
。替代語法的基本形式是把左花括號({)換成冒號(:),把右花括號(})分別換成 endif;,endwhile;,endfor;,endforeach; 以及 endswitch;。
Note: 不支持在同一個控制塊內混合使用兩種語法。
特別注意:php
switch
和第一個 case
之間的任何輸出(含空格)將致使語法錯誤。例如,這樣是無效的:數組
<?php switch ($foo): ?> <?php case 1: ?> ... <?php endswitch ?>
而這樣是有效的,由於 switch
以後的換行符被認爲是結束標記 ?>
的一部分,因此在 switch
和 case
之間不能有任何輸出:安全
<?php switch ($foo): ?> <?php case 1: ?> ... <?php endswitch ?>
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
循環是 PHP 中最複雜的循環結構。它的行爲和 C 語言的類似。 for
循環的語法是:閉包
for (expr1; expr2; expr3) statement
第一個表達式(expr1
)在循環開始前無條件求值(並執行)一次。less
expr2
在每次循環開始前求值。若是值爲 TRUE,則繼續循環,執行嵌套的循環語句。若是值爲 FALSE,則終止循環。函數
expr3
在每次循環以後被求值(並執行)。oop
每一個表達式均可覺得空或包括逗號分隔的多個表達式。
表達式 expr2
中,全部用逗號分隔的表達式都會計算,但只取最後一個結果。expr2
爲空意味着將無限循環下去(和 C 同樣,PHP 暗中認爲其值爲 TRUE)。這可能不像想象中那樣沒有用,由於常常會但願用有條件的 break 語句來結束循環而不是用 for 的表達式真值判斷。ui
考慮如下的例子,它們都顯示數字 1 到 10:this
/* 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. ?>
在 $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>\n"; } foreach ($arr as $value) { echo "Value: $value<br />\n"; } ?>
如下代碼功能也徹底相同:
<?php $arr = array("one", "two", "three"); reset($arr); while (list($key, $value) = each($arr)) { echo "Key: $key; Value: $value<br />\n"; } foreach ($arr as $key => $value) { echo "Key: $key; Value: $value<br />\n"; } ?>
用
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\n"; } ?>
以上例程會輸出:
A: 1; B: 2 A: 3; B: 4
break 結束當前 for
,foreach
,while
,do-while
或者 switch
結構的執行。
break 能夠 接受一個可選的數字參數來決定跳出幾重循環。
<?php $i = 0; while (++$i) { switch ($i) { case 5: echo "At 5<br />\n"; break 1; /* 只退出 switch. */ case 10: echo "At 10; quitting<br />\n"; 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
在循環結構用用來跳過本次循環中剩餘的代碼並在條件求值爲真時開始執行下一次循環。
Note: 注意在 PHP 中 switch 語句被認爲是可使用 continue 的一種循環結構。
continue 接受一個可選的數字參數來決定跳過幾重循環到循環結尾。默認值是 1,即跳到當前循環末尾。
<?php $i = 0; while ($i++ < 5) { echo "Outer<br />\n"; while (1) { echo "Middle<br />\n"; while (1) { echo "Inner<br />\n"; continue 3; } echo "This never gets output.<br />\n"; } echo "Neither does this.<br />\n"; } ?>
版本 | 說明 |
---|---|
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
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 ?>
(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\n"; } 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\n"; } $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
幾乎徹底同樣,除了處理失敗的方式不一樣以外。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 "\r\n"; if (true) { echo require 'file.php', "\r\n"; var_dump(@include 'file');echo "\r\n"; var_dump(require 'php.php');echo "\r\n"; var_dump((include('php.php')) == ['aa']);echo "\r\n";//注意括號,等同(include 'php.php') == ['aa'] var_dump(include('php.php') == ['aa']);echo "\r\n";//等同於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\test\test.php on line 13 Warning: include(): Filename cannot be empty in D:\php\test\test.php on line 13 PHP Warning: include(): Failed opening '' for inclusion (include_path='.;C:\php\pear') in D:\php\test\test.php on line 13 Warning: include(): Failed opening '' for inclusion (include_path='.;C:\php\pear') in D:\php\test\test.php on line 13 bool(false) PHP Warning: require(file): failed to open stream: No such file or directory in D:\php\test\test.php on line 14 Warning: require(file): failed to open stream: No such file or directory in D:\php\test\test.php on line 14 PHP Fatal error: require(): Failed opening required 'file' (include_path='.;C:\php\pear') in D:\php\test\test.php on line 14 Fatal error: require(): Failed opening required 'file' (include_path='.;C:\php\pear') in D:\php\test\test.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/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
以後接上目標位置的標記。
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.\n"; } } /* 如今能夠安全調用函數 foo()了, 由於 $makefoo 值爲真 */ if ($makefoo) foo(); function bar() { echo "I exist immediately upon program start.\n"; } ?>
PHP 中的 全部函數和類都具備全局做用域,能夠定義在一個函數以內而在以外調用,反之亦然。PHP 不支持函數重載,也不可能取消定義或者重定義已聲明的函數。
<?php function foo() { function bar() { echo "I don't exist until foo() is called.\n"; } } /* 如今還不能調用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])."\n";//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 將尋找與變量的值同名的函數,而且嘗試執行它。可變函數能夠用來實現包括回調函數,函數表在內的一些用途。
可變函數不能用於例如 echo
,print
,unset()
,isset()
,empty()
,include
,require
以及相似的語言結構。須要使用本身的包裝函數來將這些結構用做可變函數。
當調用靜態方法時,函數調用要比靜態屬性優先
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\n"; } function baz() { echo "baz\n"; } } $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\test\test.php on line 13 Notice: Undefined variable: this in D:\php\test\test.php on line 13 NULL
而在PHP 5.3中:
PHP Notice: Undefined variable: this in D:\php\test\test.php on line 7 Notice: Undefined variable: this in D:\php\test\test.php on line 7 NULL PHP Parse error: syntax error, unexpected T_FUNCTION, expecting T_PAAMAYIM_NEKUDOTAYIM in D:\php\test\test.php on line 12 Parse error: syntax error, unexpected T_FUNCTION, expecting T_PAAMAYIM_NEKUDOTAYIM in D:\php\test\test.php on line 12
Note: 能夠在閉包中使用 func_num_args(),func_get_arg() 和 func_get_args()。