首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

3.10 控制结构

控制结构(control structure)确定了应用程序中的代码流程,定义了一些执行特性,例如某条语句是否多次执行,执行多少次,以及某个代码块何时交出执行控制权。这些结构还提供一种简单的方法,可以在当前执行脚本中引入全新的代码段(通过文件包含语句)。这一节将介绍PHP语言可用的各种控制结构。

3.10.1 执行控制语句

return和declare语句分别能很好地控制一个代码块何时开始和何时结束。

1. declare()

declare()语句用于指定代码块的执行频度。当前支持的指令(directive)只有一个:tick。PHP将tick定义为一个事件,这种事件在PHP解析器执行一些低级语句时发生。tick可以用于对代码做基准测试和调试、完成简单的多任务处理或者是需要控制低级语句执行的其他任务。

这个事件在函数中定义,可通过register_tick_function()函数注册为一个tick事件。以后可以通过unregister_tick_function()函数取消该事件的注册。下面将介绍这两个函数。事件频度通过相应地设置declare函数的指令来指定,例如ticks=N,这里N是该事件调用之间发生的低级语句的数目。

l   register_tick_function()

register_tick_function()将function指定的函数注册为tick事件。

l   unregister_tick_function()

unregister_tick_function()取消以前注册的由function指定的函数。

2. return()

return()语句通常在函数体内使用,向函数调用者返回输出。如果在全局作用域内调用return(),脚本将立即结束执行。如果在使用include()或require()所包含的脚本中调用return(),控制权将返回到文件调用者。可以把参数包围在括号里,不过这是可选的。下面是一个例子:

调用此函数将向调用者返回下面的结果:

3.10.2 条件语句

条件语句使程序可以根据各种输入做出响应,基于输入值使用逻辑来辨别各种不同的条件。这对于开发计算机软件相当基本,所以,各种主流编程语言都包括大量条件语句,PHP也不例外。

1. if

if条件是所有主流编程语言中最常见的结构,为条件代码的执行提供了一种便利的方法。其语法为:

考虑一个例子,假设在用户猜对预先确定的秘密数字后要确保显示一条祝贺消息:

条件体只包含一条语句时,如果你很懒,可以不使用大括号。下面是前例的另一种形式:

注解   对于if、while、for、foreach和switch控制结构,还有另外一种语法。它将前大括号改为冒号(:),将后大括号分别改为endif;、endwhile;、endfor;、endforeach;和endswitch;。在可预见的将来这种方式仍然可用,但已经计划在未来的版本中废弃这种语法。

2. else

前面的示例有个问题,它的输出只能为猜对秘密数字的用户输出结果。所有其他用户都被忽略了,而且根本没有给出错误原因的相关提示。如果无论结果如何都要提供一个响应该怎么办?为此,需要一种办法来处理不满足if条件需求的情况,这正是else语句的功能。下面对前面的例子做了修改,为两种情况都提供了响应:

与if一样,如果只有一条代码语句,else语句的大括号可以省略。

3. elseif

if-else组合在“二选一”的情况下非常实用,即只可能有两种结果。如果有多种可能的结果怎么办?需要一种办法来考虑每一种可能的输出,这可以通过elseif语句实现。再次修改前面的秘密数字例子,这一次如果用户的猜测与秘密数字很接近(相差在10以内),则提供一个消息:

与所有条件一样,elseif在只包含一条语句时可以忽略大括号。

4. switch

可以把switch语句看作if-else组合的一种变体,如果需要比较有很多值的变量,通常会使用switch语句:

注意,在每个case块的末尾处都有break语句。如果没有break语句,就会执行所有后续的case块,直到遇到break语句为止。作为这种情况的一个例子,可以删除前例中的所有break语句,并将$category设置为weather。结果将如下:

3.10.3 循环语句

虽然形式可能有所不同,但所有流行编程语言中都必定有循环语句。这不奇怪,因为往往需要重复一段指令直到满足特定条件为止,这是程序中实现的一个常见任务,而循环机制为此提供了一种简单的方式。PHP提供了几种这样的循环机制,如果你熟悉其他编程语言,应该不会对此感到惊讶。

1. while

while语句指定了一个条件,在其嵌入代码结束执行前,必须满足这个条件。其语法是:

在下面的示例中,$count的初始值为1。然后求$count的平方,并输出。接下来$count变量加1,进行循环,直到$count的值到达5为止。

输出如下:

与所有其他控制结构一样,在while语句中可以嵌入多个条件表达式。例如,下面的while块将判断是否到达文件尾或读取并输出了5行:

对于上述条件,无论sports.txt文件的大小如何,最多只会输出sports.txt文件中的5行。

2. do...while

do...while循环条件是while的一种变体,它在代码块的结束处验证循环条件,而不是在开始处。其语法为:

while和do...while在功能上相似;唯一的区别在于while语句中的代码块可能永远不会被执行,而do...while语句中的代码块总是至少会执行一次。考虑如下例子:

输出是:

虽然11超出了while条件的限制,但内嵌的代码仍执行了一次,因为条件是在结束的时候判断的!

3. for

for语句提供了比while更复杂的循环机制。其语法为:

使用PHP的for循环,需要记住几点规则:

  ● 第一个表达式expression1在第一次循环迭代时自动计算。

  ● 第二个表达式expression2在每次迭代时进行计算。这个表达式确定是否继续循环。

  ● 第三个表达式expression3在每次循环结束时计算。

  ● 任何一个表达式都可以为空,它们可以由for块内部的逻辑所取代。

记住这些规则,考虑下面几个示例,它们都将显示一个公里/英里的对应表:

三个示例的结果都如下:

4. foreach

foreach循环结构语法最擅长循环处理数组,从数组中提取每个“键/值”对,直到获得所有项,或满足某些内部条件为止。它有两种语法形式,以下分别给出一个示例。第一种语法从数组中获取每个值,每次迭代都将指针后移(更接近数组末尾)。其语法是:

考虑一个例子。假设要输出一个由链接组成的数组:

结果将是:

第二种形式适合处理包含键和值的数组。语法如下:

修改前面的例子,假设$links数组包含链接和相应的链接标题:

数组中的每个元素都包含键和相应的值。foreach语句可以很容易地从数组中获取键/值对,如下:

结果是每个链接嵌入在相应的标题中,如下:

这种获取键/值的方法还有很多其他形式,第5章将对有关内容进行介绍。

5. break

如果包含一个break语句,将立即结束do...while、for、foreach、switch或while循环的执行。例如,下面的for循环在伪随机数是一个素数时结束:

下面是上例的输出:

6. continue

continue语句使当前循环迭代执行结束,并从下一次迭代开始执行。例如,如果$usernames[$x]中含有值"missing",下面的while体将重新开始:

结果输出如下:

3.10.4 文件包含语句

崇尚效率的程序员总是会从确保重用性和模块性的角度考虑。最普遍的方式是把功能组件隔离为单独的文件,然后在需要时重新组装。PHP提供了四种在应用程序中包含文件的语句,本节将分别介绍。

1. include()

include()语句将在其被调用的位置处包含一个文件。包含一个文件与在该语句所在位置复制指定文件的数据具有相同内容的结果。

与print和echo语句一样,使用include()时可以忽略括号。例如,假设希望包含一系列预定义的函数和配置变量,可以将这些函数和配置变量放在单独的文件中(例如,名为init.php),然后在每个PHP脚本顶部包含这个文件,如下:

还可以根据条件来执行include()语句。例如,假设一个include()语句放在if语句内,那么只有在if语句为真时才包含该文件。在条件语句中使用include()有个怪现象,它必须包围在语句块大括号中,或者用其他语句包围符括起。考虑下面两段代码中语法的不同。第一段是不正确的,因为它没有适当的块包围符。

第二段是正确的用法,在此将include()语句包围在大括号中:

关于include()语句有一个误解,以为由于所包含的代码会嵌入在PHP执行块中,所以不需要PHP转义标记。但是,事实并非如此;必须始终使用定界符。因此,不要指望只是将PHP命令放在一个文件中就能得到正确的解析,如下:

实际上,任何PHP语句都必须使用正确的转义标记包围,如下所示:

提示   所包含文件中的所有代码都会继承其调用者位置处的变量作用域。

有趣的是,只要为include()的参数提供了合法的URL,include()语句还能包含位于远程服务器的文件。如果文件所在的服务器支持PHP,通过传递必要的键/值对,可以像GET请求那样解析所包含文件中的变量,如下:

包含远程文件时必须满足两个条件。首先,allow_url_fopen配置指令必须启用。其次,必须支持URL包装器。第二个条件将在第16章详细讨论。

2. include_once()

include_once()函数的作用与include()相同,不过它会首先验证是否已经包含了该文件。如果已经包含,则不再执行include_once()。否则,则必须包含该文件。除了这一点区别,include_once与include()完全相同。

在条件语句中使用include_once()与include()一样有相同的怪现象。

3. require()

require()在很大程度与include()相同,都是将一个模板文件包含到require()调用所在的位置。

require()和include()之间有两点重要的区别。首先,无论require()的位置如何,指定文件都将包含到出现require()的脚本中。例如,即使require()放在计算为假的if语句中,依然会包含指定文件!

提示   只有启用allow_url_fopen时(这是默认值),才可以在require()中使用URL。

第二个重要的区别是:require()出错时,脚本将停止执行,而在使用include()的情况下,脚本将继续执行。一种可能的错误是require()语句不正确地引用了目标路径。

3.10.5 require_once()

随着网站越来越大,你会发现会重复地包含某些文件。这也许不是问题,但有时修改了所包含文件中的变量后,却由于后面再次包含原来的文件而被覆盖,你可能不希望出现这种情况。还可能出现另一个问题,即所包含文件中函数名的冲突。使用require_once()函数就可以解决这些问题。

require_once()函数确保文件只包含一次。在遇到require_once()后,后面再试图包含相同的文件时都将被忽略。

除了require_once()的验证过程外,其他方面都与require()相同。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论