ホームページ >バックエンド開発 >PHPチュートリアル >PHPプロセス制御機能でエラーが発生しやすいメモの共有
この記事では、プロセス制御、関数など、PHP でエラーが発生しやすい注意事項を主に共有し、皆様のお役に立てれば幸いです。
PHP は、if
、while
、for
、foreach
、スイッチコード>。代替構文の基本的な形式は、左中括弧 ({) をコロン (:) に置き換え、右中括弧 (}) をそれぞれ endif;、endwhile;、endfor;、endforeach; に置き換えます。 <code>if
,while
,for
,foreach
和 switch
。替代语法的基本形式是把左花括号({)换成冒号(:),把右花括号(})分别换成 endif;,endwhile;,endfor;,endforeach; 以及 endswitch;。
Note: 不支持在同一个控制块内混合使用两种语法。
特别注意:
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
)在循环开始前无条件求值(并执行)一次。
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. ?>
在 $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
注: 同じ制御ブロック内で 2 つの構文を混合することはサポートされていません。
特記事項:
switch
と最初の case
の間の出力 (スペースを含む) は構文エラーになります。たとえば、これは無効です: 注: elseif と else if は Curly の場合にのみ使用できることに注意してください。中括弧は同一とみなされます。コロンを使用して if/elseif 条件を定義する場合、2 つの単語の else if を使用することはできません。使用しない場合、PHP は解析エラーを生成します。 |
for ループは、PHP で最も複雑なループ構造です。その動作は C 言語の動作に似ています。 for ループの構文は次のとおりです。 |
---|---|
expr2 は、各ループが開始される前に | 評価されます。値が TRUE の場合、ループが続行され、ネストされたループ ステートメントが実行されます。値が FALSE の場合、ループは終了します。 |
各式は空にすることも、カンマで区切った複数の式を含めることもできます | 。
expr2
は、ループが無期限に継続することを意味します (C と同様、PHP は暗黙的にその値が TRUE であるとみなします)。 for 式の真偽チェックを使用する代わりに条件付き Break ステートメントでループを終了したい場合が多いため、これは思っているほど役に立たないかもしれません。 🎜🎜次の例を考えてみましょう。これらはすべて 1 から 10 までの数字を表示します: 🎜<?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 ?>🎜Excel で使用できます: 🎜
<?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 */ ?>
&
を追加して変更します。配列の要素。このメソッドは、値をコピーする代わりに 割り当てを参照
します (🎜最後に変数を unset() することを忘れないでください🎜。そうしないと、予期しない結果が発生する可能性があります)。 🎜<?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(); ?>🎜次のコードはまったく同じ機能です: 🎜
<?php declare(encoding='ISO-8859-1'); // code here ?>🎜次のコードは同じ機能です: 🎜
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 */ ?>🎜
list()
を使用してネストされた配列を解凍します🎜🎜(PHP 5 >= 5.5 .0、PHP 7)🎜PHP 5.5 では、list()
を値として指定するだけで、配列の配列を反復処理し、ネストされた配列をループ変数に解凍する機能が追加されています。 🎜<?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; } ?>🎜上記のルーチンは出力します: 🎜
<?php var_dump(include_once 'file.php'); // int(1) var_dump(include_once 'file.php'); // bool(true) ?>
for
, foreach
, while
, do-while
または switch
構造の実行。 🎜🎜break は、オプションの数値パラメーターを受け入れて、🎜 ループから抜け出す回数を決定できます。 🎜<?php for($i=0,$j=50; $i<100; $i++) { while($j--) { if($j==17) goto end; } } echo "i = $i"; end: echo 'j hit 17'; ?>🎜🎜🎜🎜バージョン🎜🎜説明🎜🎜🎜🎜🎜🎜5.4.0🎜🎜break 0は合法ではなくなりました。以前のバージョンでは、これはブレーク 1 として解釈されました。 🎜🎜🎜🎜5.4.0🎜🎜変数を引数として渡すことをキャンセルします (例: $num = 2; Break $num;)。 🎜🎜🎜🎜🎜プログラムの外側の部分 (制御ループ内ではないなど) にある
break
ステートメントはスクリプトを終了します。🎜//j hit 17🎜 は "hello" のみを表示します🎜
continue
は、ループ構造で使用され、このループ内の残りのコードをスキップし、条件が true と評価されたときに次のループの実行を開始します。 🎜注: 🎜PHP では、switch ステートメントは continue を使用できるループ構造とみなされます。 🎜🎜🎜 continue は、ループの最後までスキップするループの数を決定するオプションの数値パラメータを受け入れます。デフォルト値は 1 で、現在のループの最後にジャンプします。 🎜<?php goto loop; for($i=0,$j=50; $i<100; $i++) { while($j--) { loop: } } echo "$i = $i"; ?>🎜🎜🎜🎜バージョン🎜🎜説明🎜🎜🎜🎜🎜🎜5.4.0🎜🎜Continue 0; もはや合法ではありません。以前のバージョンでは、これは継続 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()。
call_user_func_array — 调用回调函数,并把一个数组参数作为回调函数的参数
call_user_func — 把第一个参数作为回调函数调用
create_function — Create an anonymous (lambda-style) function
forward_static_call_array — Call a static method and pass the arguments as array
forward_static_call — Call a static method
func_get_arg — 返回参数列表的某一项
func_get_args — 返回一个包含函数参数列表的数组
func_num_args — Returns the number of arguments passed to the function
function_exists — 如果给定的函数已经被定义就返回 TRUE
get_defined_functions — 返回所有已定义函数的数组
register_shutdown_function — 注册一个会在php中止时执行的函数
register_tick_function — Register a function for execution on each tick
unregister_tick_function — De-register a function for execution on each tick
相关推荐:
JavaScriptの非同期実行と操作フロー制御の例を詳しく解説
以上がPHPプロセス制御機能でエラーが発生しやすいメモの共有の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。