函式的定义及应用
本章重点
2 使用内建的PHP函式
2 浏览线上函式手册
2 使用者定义函式
2 进价技巧:可变参数、参引呼叫和可变函式
任何程序语言都有某种程序抽象处理能力(procedural abstraction,就是帮程序码某段区块命名,以便在编写其它程序码区段时能够取用)。某些script语言缺乏这种能力,而根据我们的经验,这会使复杂的伺服端程序码很快变得无法管理。
PHP用来提供这种抽象处理的机制就是函式(function)。PHP中实际上有两种类型的函式,一种是已经由PHP开发者内建在语言中,另一种是由每个PHP程序设计师自己定义的。
本章中,我们来看看如何使用PHP已提供的大量函式,然后再学会如何定义属于自己的函式。很幸运地,使用内建函式和自己定义的函式并没有什么区别。
使用函式
使用(或呼叫)函式的基本语法如下:
function_name(expression_1, expression_2,…,expression_n)
它是函式名称后带有括号并以逗号分隔输入运算式,(称为函式参数)列表的型式出现。根据具体定义,呼叫函式可以不带参数,也可以同时带入多个参数。
当PHP遇到有函式呼叫,它首先对每个参数运算式评算求值,然后使用这些值做为该函式的输入。函式执行后,回传值(如果有回传值)就是整个函式运算式的结果。
下面所列出的例子都是PHP内建函式的有效呼叫方式:
sqtr(9) //平方根函式,结果是「3」
rand(10,10+10) //回传介于「10」和「20」之间的数值
strlen(“This has 22 characters”) //回传数值「22」
pi() //回传p的近似值
这些函式分别用1,2,1和0个参数进行呼叫。
回传值与附带作用
每个函式呼叫都算是一个PHP运算式(与其它运算式一样),在程序码中包含函式只有两个原因:为了取得回传值,或者为了得到附带作用。
函式的回传值是函式运算的值。使用这个值,可以像使用其它任何运算式的求值结果一样,例如,可以把它指定到某个变数,如下所示:
$my_pi = pi();
或者,可以把它嵌入复杂的运算式中,如下所示:
$approx = sprt($approx)* sqrt($approx)
函式还可以用来实现各种不同的附带作用,其中包括将资料写入档案、资料库操作以及把内容输出示显示在浏览器视窗上。同时使用回传与附带作用出是可行的,例如,我们常常使用一个附带作用的函数并同时回传值来检查这个函数是否执行正常
。
函式的结果可以是任何型别,通常都把array型别用来当成传回多个值的函式。
函式手册
PHP的架构设计得很聪明,让它很容易由其它开发人员进行扩展延伸。其本的PHP语言本身很容易懂,出很有弹性,大多数PHP功能都存在大量的内建函式中。这是指开发人员可以自由添加新的内建函式,并且能够为PHP有所贡献,这种方式非常好,因为它不会改变PHP使用者可能依赖的任何部份。
虽然本书涵盍了许多内建函式,对其中某些函式的讲解比线上手册的讲解更详细,但所提供的手册还是函式资讯的重要参考资源。在本书中,我们会在某种程度上摘选我们想要的主题来延伸介绍,而PHP手册的内容仍旧是PHP在每个方面上最完整的参考。虽然我们希望跟随PHP的未来版本即时更新本书,但线上说明还是会关于PHP新功能的最新功能的最新资讯,包括那些还处于正在开发状态的功能。所以有空看看PHP官方网站和线上提供的不同资源可是非常有帮助的。
虽然下面的资讯在本书结稿时是正确的(第二版再版的时间是2002年)。但可能有些细节部份已过时,或者由于线上手册有了更新版本或重新组织而不再适用。
想要查寻线上手册,可进入网站,并选中右上方导航列中的「documentaion」选项标签,这样会转到一个含有各种格式且包含民其使用手册资讯的链接。我们想要看的是线是可注解的使用手册(目前连接位置在Documentation网页的View Online选项上),该手册允许使用者把自己的注解资料张贴到每一页中。[请注意:手册注解系统不是张贴问题的地方!如果有使用上的疑问,可参看邮寄清单(mailing list)部份,它位于的「support」选项标签中,或者参阅本书有关PHP资源的附录D。手册注解系统是在使用者自己理解后要用自己的话进行解释和提出意见的地方,不过确是我们能做出贡献的途径,这也是有可能就会变成未来的正式版本,这的确是我们能做出贡献的好途径,这也是指出易混淆与可能有问题的好地方,不过这里都以「英文」来沟通哦!]
使用手册中的绝大部份是函式的考次料,其中每个内建函式都有单独一份说明页面。每页从函式名称和单行的说明开始,然后是属于C语言风格的函式标头宣告(下一节会讲解到),后面是个稍长的说明,可能还有一两个例子,然后(在注解手册中)是来自使用者的注解和意见报告。
在手册中的标头
对于那些不熟悉C语言函式标头的人,函式手册的最开头部份可能会看不懂。基格式是:
return-type function-name(typle argl,type2 arg2,…);
它指示了期望的函式回传值型值,函式名称和期望的参数型别等。
下面是个基本标头描述:
string substr (string string,int startl [,int length]);
这就表示函式substr会传回一个字符串,并期望取得一个字符串和两个整数为参数。实际上,length两边的方括号表示了这个参数是选择性的,因此呼叫substr时,可带一个string字符串和一个int整数,或是带一个string字符串和两个int整数。
与在C语言中的情况不同,这些手册标头中宣告的参数型别并非是绝对必要的。如果用一个数字当成一个参数来呼叫substr,也不会有错误出现,它是由 PHP在开始执行该函式之前,把第一个参数转换成字符串。不过参数型别的确表现了函式创造者的初衷,另外最好是按照手册中注明的型别来使用函式,或者对型别转换的有关事项要有足够的了解,这样才能够保得到预期的结果。
一般来说,函式手册中用的型别名称是六种基本型别之一,或者是用它们的别名:integet(或int)、double(或float、real)、 Boolean、string、array、object、resource和NULI。另外,可以看到void和mixed的类型。Viod型态的函式根本不传回任何值,而mixed参数型别意味着参数可以是任何型别。
查询函式手册
在手册中查询关于某函式的资讯的最佳途径是什么呢?这主要取决于你的好奇心和有兴趣的部份是那种?关于函式的最常见问题是:
我要用X函式,它又该如何使用呢?
我需要完成某项Y任务,有函式能帮我完成这一任务吗?
对于第一种情况,完整版本的线上手册提供民根据函式名称的自动查询。在右上方导航列下面,「search for」文字框预设搜寻的模式是函数的名称,并且会在找到该函数后显示此函数显示此函数的网页(你也可以选取取其它搜寻对象,包含整个网站的 mailing list,这里是当你不知道所需函数名称时,但是可以猜出所需函数的概略字样时搜寻的好地方)。
以第二种情况来寻找的话,最好是使用函式参考文献(Funcrion Reference ,PHP手册中的其中一篇)的层次组织结构,该函式参考文献分成108章。例如,前面提到的substr函式在「Headers in Documentation」部分内的「String functions」部分。读者可以浏览函式参考文献的章节列表,以选择最适合你要完成的任务所属的那一章。或者,如果恰好知道一个函式的名字,该函式可能与完成的工作处于同一范围领域,此时就可以直接按下Quick Ref按钮连接到相关章节。
使用者定义的函式
使用者定义的函式在PHP中并非必要的。你也可以只用基本的语言结构和大量内建函式就能够构建出有用的Web网站了。不过如果发现自己的程序码内容变得越来越长了,而且愈来愈难了解和管理时,这表示要想一想应该把自己的某些程序码转成函式了。
什么是函式?
函式就中一种包裹某段程序码区块并给它取个名字的程序写法,这方便于以后只用一行程序码就能够使用该程序码区块。假如在写程序时,在多处都要使用到该程序码区块时,函式是最有效的方式,不过即使只使用一次,函式的建立与编写也会对程序结构有所帮助,因为可以使你的程序码更具可读性。
函式定义语法
函式可定义为以下形式:
function function-name($argument1, $argument2,..)
{
statement1;
statement2;
…
}
函式定义有四个部份:
专用的「function」一词
帮函式取的名称
函式的参数列表(以逗号分隔的$符号变数)
函式本体(大括号内的一系列叙述语句)
和变数名称一样,函式名称也必须由英文字母、数字和底线(_)组成,并且它不能以数字当开头。与变数名称不同的是,函式名称在储存前会被转换成小写,因此可将函式名称视为不区分大小写。
当呼叫使用定义的函式时发生的情况简述如下:
1. PHP会按照名字找寻该函式(如果函式还没有被定义过,则会显示错误讯息)。
2. PHP把参数(或称「实际参数」)的值替代函式定义中参数列表里的变数(或称「形式参数」)。
3. 执行函式本体的叙述语句。如果执行到叙述中「return」语句,则函式会停止执行并传回指定的值。否则,函式会一直执行到最后一道,并且不传回任何值。
请小心,有经验的程序设计师也许会注意到,前面的说明暗示了其为按值呼叫(call-by-value),而不是按参引呼叫(call-by-reference)。在本章最后一节会说明它们的差别,并示范如何进行按参引来呼叫。
函式定义的范例
举一个虚构的例子,请设想下面的这段程序码,目的是帮助我们决定购卖多少瓶装饮料(也许未来的什么时候,超商老品就已在使用可摧式的无线Web浏览器查看比较采买的价格了)。
$liters_1 = 1.0;
$price_1 = 1.59;
$liters_2 = 1.5;
$price_2 = 2.09;
$per_liter_1 = $price_1 / $liters_1;
$per_liter_2 = $price_2 / $liters_2;
if($per_literl<$per_liter2)
print(“The first deal is better! < BR >”);
else
print(“The second deal is better!< BR >”);
因为这种类型的比较在我们的Web网页程序码中随处可见,我们很想把它做成可重复使用的函式。这样做的一种途径是按照范例来重写:
function better_deal ($amount_1,$price_1,
$amount_2,$price_2)
{
$per_amount_1 = $price_1/$amount_1;
$per_amount_2 = $price_2/$amount_2;
return($per_amount_1<$per_amount_2);
}
$liters_1 = 1.0;
$price_1 = 1.59;
$liters_2 = 1.5;
$price_2 = 2.09;
if(better_deal($liters_1,$price_1,
$liters_2,$price_2))
print(“The first deal is better!< BR >”);
else
price(“The second deal is better!< BR >”);
better_deal函式抽取了以前程序码中进行算术运算和比较的那三行程序码,它带有四个数字当作参数,并传回一个Boolean 运算式的值。和任何其它Boolean值一样,可以把它嵌入到if叙述的测试部份。虽然这个函式比原来的程序码还长,但这样重写后有两个优点:可以在程序其它多个位置使用这个函式(节省了整体程序行数),如果决定改变计算方式,只需要修改一个地方就好了。
还有一种替代方案,如果价格比较就是为了印出哪笔交易更划算,那可以直接把输出显示叙述句放到函式里,如下所示:
function print_better_deal($amount_1,$price_1,
$amount_2,$price_2)
{
$per_amount_1 = $price_1 / $amount_1;
$per_amount_2 = $price_2 / $amount_2;
if($per_amout_1<$per_amount_2)
print(“The first deal is better!< BR >”);
else
print(“The second deal is better!< BR >”);
}
$liters_1 = 1.0;
$price_1 = 1.59;
$liters_2 = 1.5;
$price_2 = 2,09;
print_better_deal($liters_1,$price_1,
$liters_2,$price_2);
第一个函式使用return语句传送一个Boolean结果,然后该结果用于在一个if叙述的测试中。第二个函式没有return语句,因为它完成了其附带作用:在使用者浏览器是显示文字。当这个函式的最后一个叙述
语句执行完毕后,PHP接着执行函式呼叫后的下一条叙述语句。
形式参数与实际参数的对比
在前面的例子中,传递给函式的参数是「变数」,但并不是必须都如此处理。实际参数(即函式呼叫中的参数)可以是能够评算求值的任何运算式。在我们的例子中,可以给函式呼叫传入数字,而不用变数,如下所示:
Print_bettet_deal(1.0,1.59,1.5,2.09);
还要注意,在这个例子中有两处实际参数变数与形式参数同名的情况(如$price_1还有实际参数与形式参数名称不同的(如$liters_1与$ amount_1不同)。下一节介绍的内容中会提到两种方式都没有问题,函式的形式参数名称完全独立存在于函式外部,即使函数呼叫自己也是同样的。