>  기사  >  백엔드 개발  >  PHP 프로세스 제어 기능 오류가 발생하기 쉬운 메모 공유

PHP 프로세스 제어 기능 오류가 발생하기 쉬운 메모 공유

小云云
小云云원래의
2018-01-29 14:02:231649검색

이 기사에서는 모든 사람에게 도움이 되기를 바라며 프로세스 제어, 기능 등 PHP 오류가 발생하기 쉬운 참고 사항을 주로 공유합니다.

PHP는 if, while, for, foreach 및 전환. 대체 구문의 기본 형식은 왼쪽 중괄호({)를 콜론(:)으로 바꾸고, 오른쪽 중괄호(})를 각각 endif;, endwhile;, endfor;, endforeach;로 바꾸는 것입니다. 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>\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

break 结束当前 forforeachwhiledo-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

continue참고: 동일한 제어 블록 내에서 두 구문을 혼합하는 것은 지원되지 않습니다.
특별 참고 사항:

switch와 첫 번째 case 사이에 출력(공백 포함)하면 구문 오류가 발생합니다. 예를 들어 다음은 유효하지 않습니다.
<?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";
}
?>
switch 뒤의 개행 문자는 닫는 태그 ?>의 일부로 간주되므로 ?>에는 유효하지 않습니다. code>switch와 case 사이의 모든 출력:
<?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

if/else

<?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
?>

for

declare (directive)
    statement
첫 번째 표현식(expr1)은 루프가 시작되기 전에 무조건 한 번 평가되고 실행됩니다. 평가됩니다. 값이 TRUE이면 루프가 계속되고 중첩 루프 문이 실행됩니다. 값이 FALSE이면 루프가 종료됩니다. expr3는 각 루프 이후에 평가(및 실행)됩니다. . expr2 표현식에서는 쉼표로 구분된 모든 표현식이 평가되지만 마지막 결과만
참고: elseif와 else if는 Curly에서만 사용할 수 있다는 점에 유의해야 합니다. 중괄호는 동일한 것으로 간주됩니다. if/elseif 조건을 정의하기 위해 콜론을 사용하는 경우 두 단어로 구성된 else if를 사용할 수 없습니다. 그렇지 않으면 PHP에서 구문 분석 오류가 발생합니다. for 루프는 PHP에서 가장 복잡한 루프 구조입니다. 그 동작은 C 언어의 동작과 유사합니다. for 루프의 구문은 다음과 같습니다.
expr2는 각 루프가 시작되기 전에
각 표현식은 비어 있거나 쉼표로 구분된 여러 표현식을 포함할 수 있습니다
사용됩니다. 빈 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
 */
?>

foreach

🎜수정하려면 $value 앞에 &를 추가하세요. 배열의 요소. 이 메서드는 값을 복사하는 대신 참조 할당을 수행합니다(🎜끝에 변수를 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)
 ?>

break

🎜break는 현재 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';
?>
🎜🎜🎜🎜Version🎜🎜Description🎜🎜🎜🎜🎜🎜5.4.0🎜🎜break 0은 더 이상 유효하지 않습니다. 이전 버전에서는 이는 중단 1로 해석되었습니다. 🎜🎜🎜🎜5.4.0🎜🎜변수를 인수로 전달하는 것을 취소합니다(예: $num = 2; break $num;). 🎜🎜🎜🎜🎜프로그램 외부 부분(예: 제어 루프가 아닌)에 있는 break 문은 스크립트를 종료합니다.🎜
//j hit 17
🎜는 "hello"만 표시합니다🎜

continue

🎜continue는 루프 구조에서 이 루프의 나머지 코드를 건너뛰고 조건이 true로 평가될 때 다음 루프 실행을 시작하는 데 사용됩니다. 🎜참고: 🎜PHP에서 스위치 문은 계속을 사용할 수 있는 루프 구조로 간주됩니다. 🎜🎜🎜continue는 루프 끝까지 건너뛸 루프 수를 결정하기 위해 선택적 숫자 매개 변수를 허용합니다. 기본값은 1이며 현재 루프의 끝으로 이동합니다. 🎜
<?php
goto loop;
for($i=0,$j=50; $i<100; $i++) {
  while($j--) {
    loop:
  }
}
echo "$i = $i";
?>
🎜🎜🎜🎜Version🎜🎜Description🎜🎜🎜🎜🎜🎜5.4.0🎜🎜계속 0; 이전 버전에서는 계속 1로 해석되었습니다. 🎜🎜🎜🎜5.4.0🎜🎜변수를 매개변수로 전달하는 것을 취소합니다(예: $num = 2; 계속 $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\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(建议配合魔术常量使用)

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 "\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_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.\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 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。

可变函数不能用于例如 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\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

相关推荐:

php中流程控制语句与循环控制语句的详解

JavaScript教程--流程控制语句

자바스크립트 비동기 실행 및 연산 흐름 제어 예제에 대한 자세한 설명


위 내용은 PHP 프로세스 제어 기능 오류가 발생하기 쉬운 메모 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.