文章教程

2.8函数

9/17/2020 9:31:19 PM 人评论 次浏览

2.8 函数

在很多编程语言中都有函数这个概念。函数将为解决某一问题而编写的代码组织在一起,使得在解决同一个问题时,可以重复利用这些代码。本节将介绍PHP中函数的概念、构建和调用函数等内容。

2.8.1 PHP中函数的概念

在数学知识里,函数是由参数的定义域和在这个参数定义域上的某种规则组成的。当选定某一参数时,函数的值也是唯一确定的。例如有这样一个数学函数f(x)=2x+3,那么就有f(1)=5、f(3)=9,这里的1、3都是函数f的参数,而5、9都是这些参数对应的函数f的值。

PHP语言中的函数和数学中函数的概念很相似,只不过,PHP中的函数不仅仅是做一些数学运算,而是要完成更多、更复杂的功能。

在程序设计中,经常将一些常用的功能模块编写成函数,放在公用函数库中,供程序或其他文件使用。函数就像一些小程序,用它们可以组成更大的程序。函数之间也可以相互调用,进而完成更复杂的功能,但它们之间是相互独立的,互不隶属。

从使用角度来看,PHP的函数可以分为两种,即PHP的预定义函数和用户自定义的函数。用户可以在自己的程序或PHP文件中直接使用预定义函数,PHP提供过了大量功能丰富的预定义函数供PHP开发人员使用,极大地提高了开发效率。用户自定义的函数,是开发人员专门用来解决特定需求的功能模块。

2.8.2 定义函数和调用函数

PHP使用如下语法定义一个函数。


     function func_name(param_list)
     {statement}

其中,function是PHP的保留关键字,表示开始定义一个函数。func_name是函数名,由开发人员自行指定。函数名以字母或下划线开始,后跟任意字母、数字或下划线。函数名后的一对括号,用来存放函数的参数param_list,如果所定义的函数不需要传入参数,括号内留空,但不能没有括号。最后花括号括住的语句statement叫做函数体,它可以是单条语句,也可以是多条语句,这些语句完成函数所要实现的功能。如下代码演示了如何定义一个函数。


     function say_hello()
     {
         $name = "Jack";
         echo "Hello,".$name;
     }

这段代码很简单,它定义了一个名叫say_hello()的函数,该函数没有参数,所以函数名后面的括号内为空。函数体有两条语句:第1句是赋值语句,将某个人名赋给变量$name;第2句输出一个含这个人名的字符串。实际上,该函数的功能就是用echo语句输出一条问候语。

提示 函数的参数根据需要,可以有多个。

一个定义好的函数需要在程序其他地方使用,才能发挥它的功能。调用一个函数的最简单的用法如下。


function_name();

其中,function_name是所要调用的函数的名称。代码2-31演示了如何在程序中调用上面定义的函数say_hello()。

代码2-31 函数的调用2-31.php


     01 <?php
     02 function say_hello()
     03 {
     04     $name = "Jack";
     05     echo "Hello,".$name;
     06 }
     07 
     08 say_hello();    //
在这里调用上面定义的函数say_hello
     09 ?>

图2-26 函数的定义和调用

【代码解析】 代码第02~06行首先定义了一个函数say_hello(),但此时不会执行函数中的echo语句,因为此时只是函数的定义,计算机不需要执行任何实际代码。这段代码的第08行使用say_hello()来调用函数,此时,程序转入函数内部执行,这时执行echo语句,输出一条问候语。该程序的执行结果如图2-26所示。

另外,一个PHP文件中,函数定义的位置和调用函数的位置一般不需要确定的前后书写关系。也就是说,函数的定义可以在PHP文件的任何位置,调用也可以在PHP文件的任何位置,函数的定义不一定必须在函数调用的前面书写。例如代码2-31中函数的调用也可以写在最前面,而在最后定义函数say_hello()。

2.8.3 函数的参数和函数的返回值

2.8.2小节的函数say_hello()只能向“Jack”显示问候语,如果想向更多人显示问候语,该怎么做呢?这就是函数参数的问题。在大多数情况下,调用函数都会有数据的传递,这就是前面讲到的函数参数。将参数传递给函数,函数根据不同的参数完成不同的功能,或有不同的输出。

在函数say_hello()的例子中,如果想要向更多的人显示问候语,可以传递一个参数给函数say_hello(),这个参数就是不同的人名,在函数体内输出这个变量即可。代码2-32演示了带有参数的函数的用法。

代码2-32 调用带有参数的函数2-32.php


     01 <?php
     02 function say_hello($some_name)
     03 {
     04     echo "Hello,".$some_name;
     05     echo "<br/>";
     06     echo "<br/>";
     07 }
     08 
     09 say_hello("Jenny");         //
这里使用参数“Jenny
”调用函数say_hello
     10 say_hello("Harry");         //
这里使用参数“Harry
”调用函数say_hello
     11 say_hello("Ema");           //
这里使用参数“Ema
”调用函数say_hello
     12 ?>

图2-27 调用带有参数的函数

【代码解析】代码第02~07行定义了带有一个参数的函数say_hello($some_name),接着3次调用该函数,但每次传给函数参数的值不一样。第一次调用时,传给函数的值是“Jenny”,因此函数参数$some_name的值即为“Jenny”,这时就会输出“Hello,Jenny”。同样的道理,其他调用会显示对其他人名的问候语。程序执行结果如图2-27所示。

PHP的函数的参数可以使用默认值。代码2-33演示了函数默认参数的使用。

代码2-33 函数的默认参数2-33.php


     01 <?php
     02 function say_hello($some_name = "Jack")
     03 {
     04     echo "Hello,".$some_name;
     05     echo "<br/>";
     06     echo "<br/>";
     07 }
     08 
     09 say_hello();    //
不使用任何参数调用函数say_hello
时,函数将使用函数定义的默认参数“Jack
”
     10 say_hello("Jenny");     //
使用参数“Jenny
”调用函数say_hello
     11 say_hello("Harry");     //
使用参数“Harry
”调用函数say_hello
     12 say_hello("Ema");       //
使用参数“Ema
”调用函数say_hello
     13 ?>

图2-28 使用函数的默认参数

【代码解析】该程序对函数say_hello()做了一点小的改动,在函数定义时,第02行为函数的参数$some_name赋了默认值“Jack”。这样当程序中调用该函数,但又没有传值给函数参数时,函数就会在函数体内使用这个默认值“Jack”,如果调用时传值给函数参数,那么个这个默认值就不再起作用,而是在函数体内使用用户传入的值。程序首先使用say_hello()调用该函数,如果没有传入任何值给函数,那么这时函数体执行后,就会输出“Hello,Jack”。程序的整个执行结果如图2-28所示。

在调用一个函数之后,有时希望能得到一个确定的值,这就是函数的返回值。PHP函数中使用return语句取得函数的返回值,return语句会将函数中一个确定的值带回到调用函数的地方。示例代码2-34演示了如何获得函数的返回值。

代码2-34 函数的返回值2-34.php


     01 <?php
     02 define(PI,3.14);
     03 
     04 for($r = 3; $r<=8; $r++)                     //
从3
到8
循环
     05 {
     06     $s = get_circle_area($r);                //
调用函数get_circle_area()
     07     echo "r=$r, area=$s";
     08     echo "<br/>";
     09     echo "<br/>";
     10 }
     11 
     12 function get_circle_area($radius)            //
定义函数get_circle_area()
,参数是圆的半径
     13 {
     14     $area = PI * $radius * $radius;          //
求圆的面积
     15     return $area;                            //
返回圆的面积
     16 }
     17 ?>

图2-29 函数的返回值

【代码解析】代码第12~16行定义了一个计算圆面积的函数get_circle_area(),并在函数体最后将计算结果用return语句返回。在for循环里多次调用函数get_circle_area(),每次调用,函数get_circle_area()都会将计算结果返回赋给变量$s,接着输出圆的半径及其对应的圆的面积。程序的执行结果如图2-29所示。

2.8.4 PHP函数的传值与传址

2.8.3小节讲述的向函数传入参数是按传值方式传入的。传值的含义是指,在函数体内会生成一个传入值的复制,在函数内部对参数的修改不会影响到传入的值。因为开发的需要,有时希望在函数内部能够修改传入的值,这时就需要对函数参数使用传址方式。传址的含义是指,在函数体内真实引用传入的值,这意味着在函数体内使用的函数参数和传入的值是同一个,而不单单是传入值的一个复制。这时,在函数内部修改参数的值,同时也就修改了传入的值。

在PHP中,要想在函数参数中传址,需要定义函数时在参数前加上符号&。代码2-35演示了PHP函数如何使用传址方式传递参数。

代码2-35 传址方式传递函数参数2-35.php


     01 <?php
     02 $i = 100;
     03 
     04 function func(&$n)
     05 {
     06     $n = $n+100; //
因为传址传入变量$i
,所以这里的变量$n
引用的就是$i
本身,此句等价于$i = $i+100
     07 }
     08 
     09 echo "
调用函数func
前:\$i=$i";
     10 echo "<br/>";
     11 echo "<br/>";
     12 
     13 func($i);              //
将$i
传入函数func
,因为是传址方式,所以此时函数内的变量$n
就是变量$i
     14 echo "
调用函数func
后:\$i=$i";
     15 ?>

【代码解析】代码第04~07行定义了函数func(),该函数接收一个传址方式的参数。执行函数体内的第06行语句“$n=$n+100;”会使变量$i的值同时发生改变。程序的执行结果如图2-30所示,从中可以看出,变量$i的值原来为100,因为经过参数传址方式的调用,在函数func()中使用的就是变量$i本身,所以变量$i的值被修改为200。

为了将传值方式和传址方式进行对比,将上述函数定义改为“function func($n)”,即按传值方式传递参数给函数func(),看看结果有什么不同。请看代码2-36。

代码2-36 传值方式传递函数参数2-36.php


     01 <?php
     02 $i = 100;
     03 
     04 function func($n)                                //
定义函数func()
     05 {
     06     $n = $n+100;
     07 }
     08 
     09 echo "
调用函数func
前:\$i=$i";
     10 echo "<br/>";
     11 echo "<br/>";
     12 
     13 func($i);                                        //
调用函数func()
     14 echo "
调用函数func
后:\$i=$i.<br/>";
     15 ?>

程序的执行结果如图2-31所示。

【代码解析】从这个执行结果中可以看出,因为是传值方式传递给函数参数,在函数体内使用的是变量$i的一个复制,并不是$i本身,所以尽管在函数体内执行了加法运算,但并没有影响到变量$i的原始值。

图2-30 传址方式传递函数参数

图2-31 传值方式传递函数参数

2.8.5 变量作用域

变量作用域就是变量的有效范围。对于大多数PHP变量,作用域只能有一个。但是,在用户自定义函数中存在一个单独的局部函数范围。在一个函数内部定义的变量是局部变量,它只在本函数内有效,它的作用域就是当前函数之内。这就是说,一个在函数外部定义的变量不会在函数内部起作用;反之亦然。请看示例代码2-37。

代码2-37 变量作用域演示程序(1)2-37.php


     01     <?php
     02 $var = "some text";
     03 
     04 function test()                                 //
定义函数test()
     05 {
     06     echo $var;
     07 }
     08 
     09 test();                                         //
调用函数test()
     10 ?>

【代码解析】代码原意是想通过调用函数test()来输出变量$var的值,但通过浏览器没有看到任何输出内容。这是因为两个$var变量的作用域是不同的,第1个$var是一个全局变量,虽然它被赋值,但它的作用域(或者说它的有效范围)并不在函数test()内。这一点和C、Java等语言完全不同。在C等语言中,全局变量在函数中自动生效,除非被局部变量覆盖。第2个$var是局部变量,echo语句引用的是第2个$var(其作用域是局部的),它没有被定义(或者说没有被赋值),因此代码2-37不会在浏览器中显示出任何字符串内容。对上述代码稍作改动,读者可以更清楚地看到两个变量的有效范围。请看示例代码2-38。

代码2-38 变量作用域演示程序(2)2-38.php


     01 <?php
     02 $var = "some text";
     03 
     04 function test()                         //
定义函数test()
     05 {
     06     $var = "some text in function";
     07     echo '
这是局部变量$var
:'.$var;
     08 }
     09 
     10 echo '
这是全局变量$var
:'.$var;
     11 echo '<br/>';
     12 echo '<br/>';
     13 test();                                 //
调用函数test()
     14 ?>

代码2-38的执行结果如图2-32所示。

图2-32 变量的作用域

【代码解析】从这个执行结果可以看出,在函数test()外部定义的变量$var不会在函数内部生效。在函数test()中输出的变量$var是在其内部定义的,而在函数test()外部定义的全局变量$var并不会在函数内部生效。

如果希望在函数内部引用全局变量,需要在函数内部使用global关键字。PHP中global关键字的作用是在函数内部声明某个变量为全局变量,从而在函数内部使用该变量。代码2-39演示了global关键字的作用。

代码2-39 在函数内部使用global关键字2-39.php


     01 <?php
     02 $a = 1997;
     03 $b = 1998;
     04 
     05 function sum()                                  //
定义函数sum()
     06 {
     07     global $a,$b;
     08     $b = $a + $b;
     09 }
     10 
     11 echo '$a='.$a;
     12 echo '<br/>';
     13 echo '$b='.$b;
     14 echo '<br/>';
     15 echo '<br/>';
     16 
     17 sum();                                          //
调用函数sum()
     18 echo '$a + $b = '.$b;
     19 ?>

【代码解析】代码第02~03行首先定义了两个全局变量$a和$b,第05~09行定义了求和函数sum(),该函数内使用global关键字引用全局变量求和,并将求和结果赋值给变量$b,如代码第07行和第08行所示。这段代码的执行结果如图2-33所示。如果将代码2-39中的第07行注释掉,然后再次执行该程序,可以看到全局变量$a和$b没有在函数sum()内生效,其执行结果如图2-34所示。

图2-33 在程序中使用global关键字

图2-34 在程序中未使用global关键字

教程类别