函数

1.函数的定义与调用

1.初识函数

在编程语言中,函数是封装一段用于完成特定功能的代码。当使用一个函数时,只需关心函数的参数和返回值,就可以完成一个特定的功能。下面通过一段代码来演示函数的作用。

  1. <?php
  2. $str = 'AbCd';
  3. $upper = strtoupper($str);
  4. $lower = strtolower($str);
  5. echo $upper; //输出ABCD
  6. echo $lower; //输出abcd
  7. ?>

在上述代码中,strtoupper()和strtolower()是PHP内置的函数,用于对字符串进行大小写转换。如果PHP没有提供这两个函数,那么开发人员就要手动编写代码来实现上述工作。由此可见,使用函数可以方便程序的开发和维护。

除了使用PHP的内置函数,开发人员还可以自己定义一些函数,来将程序代码模块化,提高代码的可复用性。

  1. <?php
  2. function general_table($row,$col)
  3. {
  4. $html = '<table border="1" cellspacing="0" width=500px height=300px>';
  5. for ($i=1; $i <=$row ; ++$i) {
  6. $html .= '<tr>';
  7. for ($j=1; $j <=$col ; ++$j) {
  8. $html .= '<td></td>';
  9. }
  10. $html .='</tr>';
  11. }
  12. return $html.'</table>';
  13. }
  14. echo general_table(3,4); //生成3行4列的表格
  15. echo general_table(5,6); //生成5行6列的表格
  16. ?>

在初步了解了函数的定义与使用之后,下面我们具体看一下函数定义的语法结构。

  1. function 函数名([参数1,参数2,......])
  2. {
  3. 函数体......
  4. }

从上述语法格式可以看出,函数的定义由关键字function、函数名、参数和函数体4部分组成。关于这4部分的相关说明如下。

  • function:在声明函数时必须使用的关键字。
  • 函数名:函数名称的定义要符合PHP的标识符,且函数名是唯一的,不区分大小写。
  • [参数1, 参数2…]:外界传递给函数的值,它是可选的,多个参数之间使用逗号“,”分隔。
  • 函数体:函数定义的主体,专门用于实现特定功能的代码段。若想要得到一个处理结果,即函数的返回值,需要使用return关键字将需要返回的数据传递给调用者。

2.参数设置

对于函数来说,参数的不同设置,决定了其调用和使用方式。在对函数定义的语法格式有所了解后,接下来分别介绍几种常用的函数定义与调用方式,具体如下。

1.无参函数

  1. function shout()
  2. {
  3. return 'come on';
  4. }
  5. echo shout(); //输出结果:come on

2.按值传递参数

PHP默认支持按值传递参数,按此种方式定义的函数,在函数内部可以随意对用户传递的参数进行操作,具体示例如下。

  1. <?php
  2. function add($a,$b){
  3. $a = $a + $b;
  4. return $a;
  5. }
  6. echo add(5,7); //输出12
  7. ?>

对于有参数的函数在调用时,不仅可以如示例中一样直接传值,还可以使用变量代替。具体如下。

  1. <?php
  2. function add($a,$b){
  3. $a = $a + $b;
  4. return $a;
  5. }
  6. $x = 5;
  7. $y = 7;
  8. echo add($x,$y); //输出12
  9. ?>

3.引用传参

  1. <?php
  2. function extra(&$str)
  3. {
  4. $str .= ' and some extra';
  5. }
  6. $var = 'food';
  7. extra($var);
  8. echo $var; //输出:food and some extra
  9. ?>

在上述示例中,将函数的参数设置为引用传参后,如果函数内修改了参数3.PHP函数 - 图1var的值将会跟着变化。

4.设置参数默认值

函数参数在设置时,还可以为其指定默认值,也就是可选参数。当调用者未传递该参数时,函数将使用默认值进行操作。具体示例如下。

  1. <?php
  2. function say($p,$con = 'say "hello"')
  3. {
  4. return "$p $con";
  5. }
  6. echo say('Tom'); //输出:Tom say "hello"
  7. ?>

需要注意的是,在为函数参数设置默认值时,默认(可选)参数必须放在非默认(必选)参数的右侧,且默认值必须是常量表达式,如“123”“PHP”等。否则,函数将不会按照预期的情况工作。

5.指定参数类型

在PHP 7.0及以上的版本后,在自定义函数时,可以指定参数具体是哪种数据类型,示例如下。

  1. <?php
  2. function sum1(int $a,int $b)
  3. {
  4. return $a + $b;
  5. }
  6. echo sum1(2.6,3.8); //输出结果:5
  7. ?>

从上述示例可知,当用户调用函数时,如果传递的参数不是int类型,程序会将其强制转换为int型后再进行操作,这种方式称为弱类型参数设置。

除此之外,还可以将其设置为强类型的参数,即当用户传递的参数类型不符合函数的定义,程序会报错提醒。具体代码如下。

  1. <?php
  2. declare(strict_types = 1);
  3. function sum2(int $a,int $b)
  4. {
  5. return $a + $b;
  6. }
  7. echo sum2(2.6,3.8); //输出结果:Fatal error: ......
  8. ?>

3.变量的作用域

变量只有在其作用范围内才可以被使用,这个作用范围称为变量的作用域。在函数中定义的变量称为局部变量,在函数外定义的变量称为全局变量,具体如下所示。

  1. <?php
  2. function test()
  3. {
  4. $sum = 36; //局部变量
  5. return $sum;
  6. }
  7. $sum = 0; //全局变量
  8. echo test(); //输出结果:36
  9. echo $sum; //输出结果:0
  10. ?>

需要注意的是,默认情况下在函数中不能使用全局变量,同时局部变量的改变也不会对全局变量有任何影响,如示例中的$sum。

那么如何在函数中使用全局变量呢?PHP提供了3种方式,分别为参数传递、global关键字和超全局变量$GLOBALS。其中,参数传递的方式前面已经讲解过了,这里不再演示。其他两种方式的具体使用方式下所示。

  1. <?php
  2. function test()
  3. {
  4. //方法1:利用global关键字取得全局变量
  5. global $var;
  6. echo '全局变量$var:'.$var.'<br>'; //输出:全局变量$var:100
  7. //方法2:利$GLOBALS['变量名']访问
  8. echo '全局变量$str:'.$GLOBALS['str']; //输出:全局变量$str:php
  9. }
  10. $var = 100;
  11. $str = 'php';
  12. test();
  13. ?>

从上述代码可以看出,若要在函数内使用全局变量,在使用前要么通过global关键字取得后再使用;要么使用“$GLOBALS[‘变量名’]”的方式才可以访问。

2.函数的嵌套调用

1.嵌套调用

函数的嵌套调用,指的是在调用一个函数的过程中,调用另外一个函数,这种在函数内调用其他函数的方式称为嵌套调用。例如,班主任老师要计算每个学生语文和数学平均分,其实现思路是首先编写一个函数用于计算学生的语文和数学的总分,然后再编写一个函数用于计算学生的平均分,具体如例如下。

  1. <?php
  2. function sum($sub1,$sub2)
  3. {
  4. return $sub1 + $sub2;
  5. }
  6. function avg($sub1,$sub2)
  7. {
  8. $sum = sum($sub1,$sub2);
  9. return $sum / 2;
  10. }
  11. echo '学生A平均成绩:'.avg(50,60); //输出:学生A平均成绩:55
  12. echo '<br>';
  13. echo '学生B平均成绩:'.avg(70,80); //输出:学生B平均成绩:75
  14. ?>

程序执行流程:

①程序开始执行,调用avg()函数,并传递参数3.PHP函数 - 图2sub2。

②在avg()函数中,调用sum()函数并传递参数3.PHP函数 - 图3sub2,进入sum()函数,计算总分将结果返回到函数avg()中,同时将值赋给变量$sum。

③avg()函数接着根据sum()函数返回的值,完成平均分的计算并将结果返回。

④输出平均分,程序结束

2.递归调用

递归调用是函数嵌套调用中一种特殊的调用。它指的是一个函数在其函数体内调用自身的过程,这种函数称为递归函数。

  1. <?php
  2. function factorial($n)
  3. {
  4. if ($n == 1)
  5. return 1;
  6. return $n * factorial($n - 1);
  7. }
  8. echo factorial(4); //输出:24
  9. ?>

上述代码中定义了一个递归函数factorial(),用于实现n的阶乘计算。当3.PHP函数 - 图4n乘以factorial(3.PHP函数 - 图5%EF%BC%8C%E7%9B%B4%E5%88%B0#card=math&code=n-1%29%EF%BC%8C%E7%9B%B4%E5%88%B0)n等于1时,返回1。由此,可以得到图3-3所示的执行流程。

3.PHP函数 - 图6

图3-3描述了factorial()函数的递归调用全部过程。其中,factorial()函数被调用了4次,并且每次调用时,3.PHP函数 - 图7n的值为1时,所有递归调用的函数都会以相反的顺序相继结束,所有的返回值相乘,最终得到的结果为24。

3.函数的高级应用

1.静态变量

我们知道在函数中定义的变量,在函数执行完成后会被释放。例如,定义一个计数的函数num(),具体如下所示。

  1. <?php
  2. function num()
  3. {
  4. $i = 1;
  5. echo $i;
  6. ++$i;
  7. }
  8. ?>

从上述示例可知,不论调用多少次num()函数,输出的3.PHP函数 - 图8i赋值为1。因此,若想要局部变量在函数执行完成后,依然保留局部变量的值,则可以利用static关键字在函数中声明静态变量。将上述示例中的第3行代码修改成如下形式。

  1. static $i = 1;

修改完成后。第1次调用函数num()输出1,第2次调用函数num()会输出2,依次类推,就可以轻松得到num()函数被调用的次数,使函数中定义的变量不会在函数调用完成后被释放掉,保存了每次调用函数时改变的值。

2.可变函数

前面我们学习了可变变量,它的实现是在一个变量前添加一个“$”符号,就变成了另外一个变量。同理,可变函数的实现就是在一个变量名后添加一对圆括号“()”,让其变成一个函数的形式,然后PHP就寻找与变量值同名的函数,并且尝试执行它,具体如例3-4所示。

  1. <?php
  2. function shout()
  3. {
  4. echo 'come on......';
  5. }
  6. $funcname = 'shout'; //定义变量,其值是函数名称
  7. echo $funcname(); //利用可变变量调用函数,输出:come on......
  8. ?>

在上述代码中,变量3.PHP函数 - 图9funcname()的方式进行调用,最后在浏览器中输出“come on….”。

在实际编程中,使用可变函数可以增加程序的灵活性,但是滥用可变函数会降低PHP代码的可读性,使程序逻辑难以理解,给代码的维护带来不便,所以在编程过程中要尽量少用可变函数。

3.回调函数

回调函数(callback)指的就是具有callable类型的函数,一般用作参数的传递。如PHP内置函数call_user_func()可以接受用户自定义的回调函数作为参数,如下所示。

  1. <?php
  2. function sum($a,$b)
  3. {
  4. return $a + $b;
  5. }
  6. echo call_user_func('sum',4,5); //输出结果:9
  7. ?>

在上述示例中,call_user_func()函数的第1个参数表示callable类型的回调函数名称,如sum()函数。第2个和第3个参数表示向回调函数传递的参数,如4和5。因此,程序执行函数call_user_func()后,将调用sum()函数并返回执行结果。

4.匿名函数

匿名函数就是没有函数名称的函数,也称作闭包函数,经常用作回调函数参数的值。对于临时定义的函数,使用匿名函数无需考虑函数命名冲突的问题,具体示例如下所示。

  1. <?php
  2. $sum = function($a,$b){ //定义匿名函数
  3. return $a + $b;
  4. };
  5. echo $sum(100,200); //输出:300
  6. ?>

在上述代码中,定义一个匿名函数,并赋值给变量$sum,然后通过“变量名()”的方式调用匿名函数。需要注意的是,此种匿名函数调用的方式看似与可变函数的使用类似,但实际上不是,若通过var_dump()对匿名函数的变量进行打印输出,可以看到其数据类型为对象类型。

在开发中,若要在匿名函数中使用外部的变量,需要通过use关键字实现,具体使用示例如下。

  1. <?php
  2. $c = 100;
  3. $sum = function($a,$b) use($c){ //定义匿名函数
  4. return $a + $b + $c;
  5. };
  6. echo $sum(100,200); //输出:400
  7. ?>

在上述代码中,若要在匿名函数中使用外部变量,该变量需先在函数声明前进行定义。然后在定义匿名函数时,添加use关键字,其后圆括号“()”中的内容即为要使用的外部变量列表,多个变量之间使用英文逗号“,”分隔即可。

除此之外,匿名函数还可以作为函数的参数传递,实现回调函数,具体使用示例如下。

3.PHP函数 - 图10

在上述代码中,calculate()函数的第3个参数$func是一个回调函数,通过这种方式,可以将函数的一部分处理交给调用时传递的另一个函数,极大增强了函数的灵活性。

4.PHP的内置函数

对于常用的功能,除了自定义函数外,PHP还提供了许多内置函数。例如,针对字符串的截取、替换等操作PHP专门提供了对应的函数,针对数据的求和、平均数等操作提供了对应的数学函数以及获取时间日期的函数等。

1.字符串函数

函数名称 参数 功能描述
strlen() 获取字符串的长度
strpos() 查找字符串首次出现的位置
strrpos() 计算指定字符串在目标字符串中最后一次出现的位置
str_replace() 子字符串替换
substr() 返回字符串的子串
explode() 使用一个字符串分割另一个字符串
implode() 用指定的连接符将数组拼接成一个字符串
trim() 去除字符串首尾处的空白字符(或者其他字符)
str_repeat() 重复一个字符串
strcmp() 用于判断两个字符串大小

2.数学函数

函数名 功能描述
abs() 取绝对值
ceil() 向上取最接近的整数
floor() 向下取最接近的整数
fmod() 取除法的浮点数余数
is_nan() 判断是否为合法数值
max() 取最大值
min() 取最小值
pi() 取圆周率的值
pow() 计算x的y次方
sqrt() 取平方根
round() 对浮点数进行四舍五入
rand() 生成随机整数

3.时间日期函数

在使用PHP开发Web应用程序时,经常会涉及日期和时间管理。例如,倒计时、用户登录时间、新闻发布时间、购买商品时下订单的时间等。为此,PHP提供了内置的日期和时间处理函数,满足开发中的各种需求。

函数名 功能描述
time() 取得当前的UNIX时间戳
date() 格式化一个本地时间/日期
mktime() 获取指定日期的UNIX时间戳
strtotime() 将字符串转化成UNIX时间戳
microtime() 获取当前UNIX时间戳和微秒数

1.UNIX时间戳

UNIX时间戳是一种时间的表示方式,它的存在是为了解决编程环境中时间运算的问题。例如,在处理时间和日期时,推算起来会比较复杂,因其除了时间进位以外,还要涉及不同的月份天数等,所以使用简单的运算是无法解决的。

UNIX时间戳(UNIX timestamp)定义了从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数,以32位二进制数表示。其中,1970年01月01日零点也叫作UNIX纪元,具体示例如下。

  1. <?php
  2. echo time(); //输出结果:1619008603
  3. echo '<br>';
  4. echo mktime(0,0,0,4,21,2021); //输出结果:1618934400
  5. echo '<br>';
  6. echo strtotime('2021-4-21'); //输出结果:1618934400
  7. echo '<br>';
  8. echo microtime(); //输出结果:0.70563600 1619008603
  9. echo '<br>';
  10. echo microtime(true); //输出结果:1619008603.7056
  11. ?>

在上述示例中,time()函数用于获取当前时间的UNIX时间戳,mktime()和strtotime()函数可将给定的日期时间转换成UNIX时间戳,前者的参数分别表示“时分秒月日年”,后者可以是任意时间的字符串。函数microtime()用于获取当前UNIX时间戳和微秒数,不设置参数时,返回值前面一段数字表示微妙数,后面一段数字表示秒数;设置参数时,小数点前表示秒数,小数点后表示微秒数。

2.格式化时间戳

对于用户来说,时间戳的直接输出,会让其看到一个毫无意义的整型数值。为了将时间戳表示的时间以友好的形式显示出来,可以对时间戳进行格式化,具体示例如下。

  1. <?php
  2. echo date('Y-m-d H:i:s'); //输出结果:2021-04-21 20:39:58
  3. echo '<br>';
  4. echo date('Y-m-d',1618934400); //输出结果:2021-04-21
  5. ?>

在上述date()函数的示例中,第1个参数表示格式化日期时间的样式,第2个参数表示待格式化的时间戳,省略时表示格式化当前时间戳。关于date()函数格式化日期的常用字符表示含义如表所示:

3.PHP函数 - 图11