函数的概念与作用

函数不是数!函数是一种代码形式(语法形式)。函数是将“若干行代码”以一种语法形式包装成的一个整体。

该整体可以做到“需要的时候就去执行它”(就是执行其中的若干行代码)。

函数是解决在不同情形(不同代码位置)下需要执行相同代码的有效方式——即所谓代码重用

函数通常用于“专业的事由专业的人来做”这种现实世界的常见现象。

  • 比如油条摊:专门做油条,顾客随时需要,就随时可以买(付钱就可以)。
  • 比如轮胎厂:专门生产不同型号轮胎,汽车制造厂随时需要就随时提供(付钱)。
  • 比如豆浆机:专门制作豆浆,人们随时需要豆浆就随时可以启动豆浆机制作豆浆(提供豆子和水)。

函数的定义与调用

定义语法形式:

定义语法形式
定义语法形式

调用语法形式:

函数名($实参1,$实参2, ...... ); //实参就是实际参数,是数据

说明

  1. 函数名的命名规则,跟变量名一样;
  2. 定义函数的目的就是为了以后能够调用;
  3. 调用函数,其实就是执行函数中代码;
  4. 形参,其实就是变量,是只能在该函数内部使用的变量;
  5. 实参,其实就是数据,是会传入函数内部的数据(是一一对应地赋值给形参变量);

案例演示:写一个函数,可以给定一个半径,求对应圆面积。

define("PI", 3.14);
//求半径为r的圆的面积
function circleArea($r)
{
    $s = PI * $r * $r;
    return $s;    //返回计算的结果
}
$s1 = circleArea(1);
echo "<br>半径为1的圆面积为:$s1";
$s2 = circleArea(3);
echo "<br>半径为3的圆面积为:$s2";
$s3 = circleArea(5.7);
echo "<br>半径为5.7的圆面积为:$s3";

课堂练习:写一个函数,可以给定长宽高,求对应一个长方体的表面积。

//$c, $k, $g分别代表:长,宽,高
function biaomianji($c, $k, $g)
{
    $s = ($c*$k + $c*$g + $k*$g)*2;
    return $s;
}

$biaomianji1 = biaomianji(1, 1, 1);
echo "<br>表面积1为:$biaomianji1";

$biaomianji2 = biaomianji(1, 2, 3);
echo "<br>表面积2为:$biaomianji2";

$biaomianji3 = biaomianji(5, 2, 3);
echo "<br>表面积3为:$biaomianji3";

函数执行原理(重点/难点)

程序总是运行在一个“内存空间”。

程序开始执行的位置所在的空间,可以称之为“主运行空间”。

实际上,通常函数外面的那些程序,都是运行在主空间中。

那么,函数的运行,就相对独立了——每个函数的每次调用,都是运行在单独的一个自己的空间中。

如下所示:

函数执行原理
函数执行原理

函数参数(重点)

形参(形式参数)

就是定义函数的时候,在函数名后的小括号中给出的变量名。

形参,只能在函数内部使用——即该变量的使用范围仅仅局限于当前函数内部。

形参的本质是变量!

实参(实际参数)

就是调用函数的时候,在函数名后的小括号中给出的数据值。

实参的本质是数据!

函数参数的传值方式

含义:实参变量的值,以什么方式传给形参。

说明:其前提是:实参是一个变量的情况。所以其实这里讨论的是:两个变量的传值方式问题。

默认情况下是值传递。可以使用“&”符号设定为引用传递,形式如下:

$num1 = 1;
$num2 = 2;

function demo(&$num1, &$num2) {
    // 函数执行代码
}

此时,在函数内部,对该形参变量改变其值,则对应的实参变量(在函数外部)的值也改变了。

案例演示:

//函数参数的传值演示:
function f1($p1, &$p2)
{
    $p1++;
    $p2++;
    $result = $p1+$p2;
    return $result;
}
$v1 = 10;
$v2 = 20;
$s = f1($v1, $v2);
echo "<br>s=$s, v1=$v1, v2=$v2";

$v3 = 30;
$v4 = 40;
$s2 = f1($v3, $v4);    //这行可以
//$s2 = f1(30, 40);        //这行报错!40不能“引用方式”传给$p2
                //即:引用传递的形参,必须对应实参变量(不能实参数据)
echo "<br>s2=$s2, v3=$v3, v4=$v4";

利用引用传递,我们可以使用函数对某位外部变量进行改变操作。

形参的默认值

形参可以设定默认值。形式为:$形参名 = 某值。

设定默认值的形参,只能放在没有设定默认值的形参的后面(右边)。

设定了默认值的形参对应的实参可以不提供数据,此时函数就会使用该默认值当做实参的值。

function demoFun($num1, $num2, $num3 = 3, $mark = true) {
    // 函数代码块
}

demoFun(1,2);

demoFun(1, 2, 5);

demoFun(1, 2, 4, false);

则此时调用上述函数,以上形式都可以。

案例演示:定义一个函数,该函数可以计算给定半径的球的体积,其中圆周率π默认使用3.14,也可以根据不同精度的需要给定不同的圆周率。

<?php 
//定义一个函数,该函数可以计算给定半径的球的体积,
//其中圆周率π默认使用3.14,也可以根据不同精度的需要给定不同的圆周率。

function ball_tiji($r, $pi=3.14)
{
    $s = $pi * 4 * $r * $r * $r / 3;
    return $s;
}
$s1 = ball_tiji(1);
echo "<br>半径为1的球的体积为:$s1";

$s2 = ball_tiji(1, 3.1416);
echo "<br>半径为1的球的体积为:$s2";

函数返回值(重点)

含义:一个函数在执行结束时,可以让其返回一个数据,这就是函数的返回值。

语法:return 要返回的数据;

说明:

  1. 一般情况下一个函数执行结束都是需要返回一个数据值的。
  2. 函数也可以在执行的中途返回数据,此时,函数也是结束了的。
  3. 一个函数执行得到的返回值,可以在任何需要数据的场合使用,跟使用一个变量数据一样。

演示:

计算两数的平方和与两数的平方差相除的结果。

//计算两数的平方和与两数的平方差相除的结果。
function suibian($x, $y)
{
    $he = $x*$x + $y*$y;
    $cha = $x*$x - $y*$y;
    if($cha != 0){
        return $he / $cha;
    }
    else
    {
        return "数据有误(两个数不能相等)";
    }
    
}
$v1 = suibian(3,4);
echo "<br>平方和差相除为:" . $v1 ;
echo "<br>平方和差相除为:" . suibian(5,3) ;
echo "<br>平方和差相除为:" . suibian(4,4) ;

另外,return语句也可以不带后面的数据,此时,就只是单纯地结束函数,并不返回数据(也可以说返回null这个空数据)。

演示:

//演示函数return语句之后不再执行!
function f1( $p1 , $p2 )
{
    $s1 = $p1 + $p2;
    return $s1;
    $s2 = $p1*$p1 + $p2*$p2;
    return $s2;
}
$result1 = f1(1,2)*4-5;
echo "<br>result1 = $result1";
echo "<br>";
echo f1(1,4);
echo "<hr>";

//演示函数不返回值,只使用return 结束的情形:
function f2(){
    echo "<hr>";
    return ;        //这里就结束函数了(没有返回数据)
    echo "<hr>";    //此行不执行!
}
f2();
$v2 = f2();    //结果$v2是什么?实际是null
var_dump($v2);    //null

将上述案例加强一个判断条件:当两个数相等时,报错并结束,不返回数据。

结论:只要执行到return语句,函数就会结束,是否返回数据,看该行代码。

可变函数

含义:所谓可变函数,就是函数名是一个变量的情形。

可变函数实际上就是在调用函数的时候,使用一个变量来表示函数名,并用该变量去调用函数。

注意:定义函数的时候,不可以使用可变函数名!

对比:

  • 可变变量,就是变量名是一个变量,比如:$$v1;
  • 可变函数,就是函数名是一个变量,比如:

调用函数f1的语法是这样:f1();

可以使用可变函数的语法来调用: $func_name = “f1”; $func_name();//此时实际就是调用f1

可变函数的本质是:一个变量的内容是一个字符串,该字符串是一个函数的名字,比如:

function f1(){ ....... }

function f2(){ ....... }

$f = “f1”;

$f(); //调用了函数f1,这就是可变函数!!

$f = “f2”;

$f(); //调用了函数f2,这就是可变函数!!

$f = “f3”;

$f(); //报错!因为没有f3这个函数

可变函数应用举例:

function do_jpg($f){
    echo "<br>处理jpg图片。。。。";
}
function do_gif($f){
    echo "<br>处理gif图片。。。。";
}
function do_webp($f){
    echo "<br>处理webp图片。。。。";
}
$file = $_GET['file_name'];    //用户上传的文件名,比如123.jpg, 456.gif
//haystack表示:干草堆,neele:缝衣针
//strrchr()用于在一个字符串haystack中找出指定的某个字符串needle出现的最后位置往后的所有字符
//$houzhui =  strrchr(haystack, needle)
$houzhui =  strrchr($file, '.');//得到类似这样: ".gif",  ".jpg", ".webp"
//substr($v1,位置p,[长度n]):取出字符串v1中从位置p开始之后的n个字符
//如果长度n省略,则一直取到最后
//比如:substr('abcdef', 3, 2): 'de'
//比如:substr('abcdef', 3, 3): 'def'
//比如:substr('abcdef', 3, 4): 'def'
//比如:substr('abcdef', 3):     'def'
$houzhui = substr($houzhui,1);    //得到类似这样:"gif",  "jpg", "webp"

$func_name = "do_" . $houzhui;    //构建出可以使用的函数名,可能是上述3个函数之一的名字
$func_name( $file );//这就是可变函数的使用!实际使用的可能是:do_jpg(), do_gif(), do_webp()之一

匿名函数

含义:就是一个“定义时没有名字”的函数。

此时,就面临一个问题,那就是:没有名字,怎么调用呢?

实际上,此时它通过另一个方式来调用,如下所示:

$f1 = function (形参...) { ....... } //这是定义匿名函数的形式。

$f1(实参); //这就是调用该调用。可见其调用,跟可变函数的写法非常类似。

案例:定义一个匿名函数,该函数可以计算两个数的最小公倍数,并调用该函数算出6和8的最小公约数。

//定义一个匿名函数,该函数可以计算两个数的最小公倍数,
//并调用该函数算出6和8的最小公约数。

$gongbeishu = function ($n, $m){
    for($i = $n; $i >= $n; $i+=$n){
        if($i % $m == 0)
        {
            return $i;
        }
    }
};

$result1 = $gongbeishu(3, 5);    //应该15
echo "<br>result1 = $result1";
$result2 = $gongbeishu(6, 8);    //应该24
echo "<br>result2 = $result2";

系统常用函数介绍

PHP语言,以函数极大丰富而闻名于世。

看手册,查手册,并作为一种学习的习惯:

跟函数有关的函数

  • function_exists(“函数名”):判断一个函数是否已经存在;
  • func_get_arg( \$n ): 在函数内部可用,用于获得第n个实参(n从0开始算起)
  • func_get_args(): 在函数内部可用,用于获得所有实参,结果是一个数组
  • func_num_args(): 在函数内部可用,用于获得实参的个数

上面3个函数,可以让我们在自定义的函数内部,直接访问(使用)实参数据,而不依赖于形参变量。

这种特性,可以给我们定义某种“不确定有几个数据需要计算的”场合。

案例:定义一个函数,该函数可以求出所给定的若干个数据中的奇数的和。

//定义一个函数,该函数可以求出所给定的若干个数据中的奇数的和。
function jishuhe()
{
    $all_args = func_get_args();    //得到所有实参,是一个数组!
    $count = count($all_args);        //取得数组的长度(元素个数)
    $sum = 0;
    //对该数组(也就是所有实参)进行遍历循环
    for($i = 0; $i < $count; $i++)
    {
        if($all_args[$i] % 2 == 1)
        {
            $sum += $all_args[$i];    //累加器
        }
    }
    return $sum;
}

$he1 = jishuhe(1, 5, 2, 8, 7);
echo "<br>和1为:$he1";
$he2 = jishuhe(11, 3, 2, 8, 4, 10, 12);
echo "<br>和2为:$he2";

字符串有关常用函数

  • 输出与格式化:echo , print, printf, print_r, var_dump.
  • 字符串去除与填充:trim, ltrim, rtrim, str_pad
  • 字符串连接与分割:implode, join, explode, str_split
  • 字符串截取:substr, strchr, strrchr,
  • 字符串替换:str_replace, substr_replace
  • 字符串长度与位置: strlen, strpos, strrpos,
  • 字符转换:strtolower, strtoupper, lcfirst, ucfirst, ucwords
  • 特殊字符处理:nl2br, addslashes, htmlspecialchars, htmlspecialchars_decode,

手册》函数参考》文本处理》字符串》字符串函数:https://www.php.net/manual/zh/ref.strings.php

常用数学函数(重点)

  • max: 取得若干个数据中的最大值
  • min: 取得若干个数据中的最小值
  • round: 对某个数据进行四舍五入(可以设定保留几位小数)
  • ceil: 对某个数“向上取整”:将一个数据往上找出其小的一个整数(含其本身)。
  • floor: 对某个数“向下取整”:将一个数据往下找出其大的一个整数(含其本身)
$n1 = floor(4.1); //4

$n2 = floor(4.9); //4

$n3 = floor(4); //4

$n4 = floor(-4.1); //-5
  • abs: 取得某个数据的绝对值
  • sqrt: 计算某个数的开方值
  • pow: 对某个数进行“幂运算”(就是获得某个数的若干次方)
$n1 = pow(3, 2); //3的2次方,9

$n2 = pow(2, 3); //8

$n3 = pow(1.5, 2); //2.25

$n4 = pow(1.5, 2.5); //。。。。。1.5的2.5次方

$n5 = pow(9, 0.5); //3,就是开方,相当于sqrt()
  • rand: 获得某两个数之间的随机整数(含该两个数)
  • mt_rand: 获得某两个数之间的随机整数(含该两个数),比rand更快。
$n1 = mt_rand(0, 10); //随机数在0-10之间(含)

手册》函数参考》数学扩展》Math》Math函数:https://www.php.net/manual/zh/book.math.php

演示案例:定义一个函数,该函数可以返回所给定的任意两个数字之间的随机整数。

//定义一个函数,该函数可以返回所给定的任意两个数字之间的随机整数。

function suiji($p1, $p2)
{
    if($p1>$p2)
    {
        $num_max = $p1;
        $num_min = $p2;
    }
    else
    {
        $num_max = $p2;
        $num_min = $p1;
    }
    return mt_rand($num_min, $num_max);
}
echo "<br>10-20的随机数:" . suiji(10, 20);
echo "<br>20-15的随机数:" . suiji(20, 15);
echo "<br>15-15的随机数:" . suiji(15, 15);

$num  = range(10, 30);
shuffle($num);
for ($i=0; $i <6 ; $i++) { 
    echo $num[$i] &ensp;
}

常用时间函数

  • time:获得当前时间(精确到秒),结果其实一个“整数”而已,代表从1970年1月1日0:0:0秒到当前时刻的秒数。
  • microtime:获得当前时间(可以精确到微秒)
  • mktime:创建一个时间数据,参数为:时、分、秒,月、日、年
  • date:将一个时间转换为某种字符串形式
  • idate:取得一个时间的某个单项数据值,比如idate(“Y”)取得年份数
  • strtotime:将一个字符串“转换”为时间值;
  • date_default_timezone_set:在代码中设置“时区”
  • date_default_timezone_get:在代码中获取“时区”

案例:课堂电脑性能大比拼:计算从1加到1000万,看花了多少时间?

做法:先获得一个时间,然后计算,然后再获得一个时间,后一个时间,减前一个时间,就是耗时。

//演示时间函数:

echo "<br>从1970.1.1 0:0:0到现在共经过了这么多秒:". time();
echo "<br>从1970.1.1 0:0:0到现在共经过了这么多秒:". microtime(true);
echo "<br>从1970.1.1 0:0:0到现在共经过了这么多秒:". microtime(false);

echo "<hr>";
/*
课堂电脑性能大比拼:
计算从1加到1000万,看花了多少时间?
做法:先获得一个时间,然后计算,然后再获得一个时间,
后一个时间,减前一个时间,就是耗时。
*/
$t1 = microtime(true);    //获得当前时间
$n = 0;
for($s=1;$s<=10000000;$s++)
{
    $n+=$s;
}
$t2 = microtime(true);    //获得当前时间
$t3 = $t2 - $t1;
echo "$n <br>";
echo $t3;