🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 函数 [toc] ## 1. 语法 函数是实现代码复用的重要方式,在所有编程语言中均如此 ```php function 函数名称(参数列表) { // 函数体 return 返回值; } ``` | 序号 | 名称 | 描述 | | ---- | ----------- | ------------------------------------------ | | 1 | `function` | 声明函数 | | 2 | `函数名称` | 符合 PHP 标识符命名规范,不区分大小写 | | 2 | `参数列表` | 零个或多个接收外部传入到函数的变量 | | 2 | `{...` | 创建出一个封闭的函数作用域 | | 2 | `函数体` | 由零个可多个合法的 PHP 语句组成 | | 2 | `return 值` | 将执行结果返回函数调用者[可选] | | 2 | `...}` | 函数执行结束,如果没有`return`,则返回`null` | 示例代码: `demo1.php` ```php # 函数语法 // 声明: function 关键字 function func1($a, $b) { return $a + $b; } // 调用: 按名调用 echo func1(10, 20); ``` --- ## 2. 类型 | 序号 | 类型 | 语法 | 描述 | | ---- | ---------- | ------------------------- | --------------------------------------- | | 1 | 自定义函数 | `function getName(){...}` | 用户根据业务需求创建 | | 2 | 系统函数 | `substr(), count()...` | 也叫预定义函数,不必声明直接调用 | | 3 | 可变函数 | `$funcName();` | 函数名使用变量表示 | | 4 | 匿名函数 | `$f = function (){...}` | 也叫"闭包"或"函数表达式",常用做回调处理 | 示例代码: `demo2.php` ```php <?php # 函数类型 // 1. 自定义函数 function getPrice($money, $discount) { return $money * $discount; } echo '实付金额 = ' . getPrice(5000, 0.8); echo '<hr>'; // 2. 系统函数 $str = '钟南山团队入围2020年度国家科技奖提名'; // 仅获取前5个中文字符 echo mb_substr($str, 0, 5); echo '<hr>'; // 3. 可变函数 // 仍以前面已声明的函数: getPrice()为例 $funcName = 'getPrice'; // 被调用的函数名称保存到一个变量中 // 这个功能很实现,在后面课程中会看到更多应用 echo '实付金额 = ' . $funcName(8000, 0.7); echo '<hr>'; // 3. 匿名函数 $f = function ($money, $num) { return $money * $num; }; echo '实付金额 = ' . $f(100, 20); echo '<br>'; // 匿名函数也叫闭包,可以继承父作用域中的变量 $discount = 0.8; // $discount 是父作用域中的变量,这个父作用域可以是全局, 也可以是父函数 // 父作用域是全局 $getAmount = function ($money, $num) use ($discount) { $amount = $money * $num; return $amount > 2000 ? $amount * $discount : $amount; }; echo '实付金额 = ' . $getAmount(120, 20); echo '<br>'; // 父作用域是函数 $f = function ($discount) { $getAmount = function ($money, $num) use ($discount) { $amount = $money * $num; return $amount > 2000 ? $amount * $discount : $amount; }; return $getAmount; }; echo '实付金额 = ' . $f($discount)(120, 20); ``` --- ## 3. 返回值 - 函数必须要有返回值 - 函数必须是遵守**单值返回**原则 | 序号 | 场景 | 描述 | | ---- | ---------- | --------------------------------- | | 1 | `return` | 可以返回任何类型的值,包括函数类型 | | 2 | 无`return` | 遇到`}`也会返回, 默认返回`null` | - 如果需要返回多个值,可以通过以下手段 | 序号 | 返回值类型 | 描述 | | ---- | ----------- | ------------ | | 1 | `string` | 字符串拼接 | | 2 | `array` | 数组 | | 3 | `json` | JSON 字符串 | | 4 | `serialize` | 序列化字符串 | > json 和序列化,使用时需要进行解码操作 示例代码: `demo3.php` ```php <?php # 函数返回值 // 单值返回,前面已经有了许多案例,重点放在多值返回上 // 1. 通过拼装字符串实现 function demo1() { $status = 1; $message = '成功'; return $status . ', ' . $message; } echo demo1(); // 字符串拼装返回非常适合处理大量变量与html标签的混写 // 字符串拼装返回多值有许多限制,并且对返回值的解析处理非常麻烦 echo '<hr>'; // 2. 通过数组返回多值 function demo2() { return ['status' => 1, 'message' => '验证成功']; } echo demo2()['status'] === 1 ? demo2()['message'] : '验证失败'; // 返回值如果仍在php程序中处理,这样做很方便 // 开发中, 通常返回值都是要交给前端处理的,转为JSON格式更方便 echo '<hr>'; // 3. 通过JSON格式返回多值 // json是一种通用的,轻量级数据表示格式,使用javascript对象字面量表示数据 // 几乎所有编程程序,都支持定义和解析json格式的数据,请放心使用 // 当前后端时行数据交互时, json格式几乎成了除字符串之外的唯一选择 // json本质上仍是字符串, 只不过具有一些特殊格式,需要进行解析罢了 function demo3() { // json_encode(): json编码函数,将数据编码为json格式字符串返回 return json_encode(['status' => 1, 'message' => '验证成功']); } // json_decode():json解码函数, 解析json格式字符串,默认返回对象,true表示返回数组 $data = json_decode(demo3(), true); echo '<pre>' . print_r($data, true) . '</pre>'; echo '<hr>'; // 4. 通过序列化返回多值 // 序列化可以将程序中的变量/数据做持久化保存,可以进行传输,保存到文件中等 // 与json一样, 序列化也有序列化与反序列二种操作 function demo4() { return serialize(['status' => 1, 'message' => '验证成功']); } // 查看序列化的格式化字符串 echo demo4(), '<br>'; // 反序列化 $data = unserialize(demo4()); echo '<pre>' . print_r($data, true) . '</pre>'; ``` --- ## 4. 参数 - 调用者可以通过参数将数据传递到函数中 - 参数是以逗号分隔的表达式列表 - 参数按照从左到右的顺序求值 参数类型 | 序号 | 类型 | 描述 | | ---- | -------- | -------------------- | | 1 | 值参数 | 默认传参方式 | | 2 | 引用参数 | 改变原始调用参数值 | | 3 | 默认参数 | 调用时允许省略的参数 | | 4 | 剩余参数 | 调用参数数量不确定 | 示例代码: `demo4.php` ```php <?php # 函数参数 // 1. 值参数: 默认 function demo1($arg) { return $arg *= 2; } $value = 100; echo demo1($value), '<br>'; echo $value, '<br>'; echo '<hr>'; // 2. 引用参数 // 引用传参: 参数前添加地址引用符 function demo2(&$arg) { // 函数内部更新了调用参数,则直接影响到原值 return $arg *= 2; } $value = 100; echo demo2($value), '<br>'; echo $value, '<br>'; echo '<hr>'; // 3. 默认参数 // 参数列表中,允许有必选参数和默认参数二大类, 默认参数必须排列在必选参数的后面 // 默认参数决定了函数的默认行为,如果函数默认行为满足要求,显然不传参调用更方便 // 默认参数也允许用户根据自身需求,传入自定义参数,对函数的行为进行干预 function demo3($a, $b, $opt = '+') { $res = 0; switch ($opt) { case '+': $res = "$a + $b = " . ($a + $b); break; case '-': $res = "$a - $b = " . ($a - $b); break; case '*': $res = "$a * $b = " . ($a * $b); break; case '/': $res = "$a / $b = " . ($a / $b); break; default: $res = '非法操作符'; } return $res; } // 如果用户不传第三个参数,则使用默认参数,即默认执行:+ 加法 echo demo3(10, 20), '<br>'; // 传入用户自定义操作, 如*, 乘法 echo demo3(10, 20, '*'), '<br>'; // 传入非法数据: # echo demo3(10, 20, '#'), '<br>'; echo '<hr>'; // 4. 剩余参数 function demo4($a, $b, $c) { return $a + $b + $c; } // 计算三数之和 echo demo4(1, 2, 3), '<br>'; // 如果计算五数之和,甚至更多数的求和,难道要这样一直写下去呢? // 其实函数的参数列表中的参数,只是占位符罢了,可以为空的 // 函数内部可以通过其它方式来获取到调用参数的 // php5.5之前,可以用以下三个函数来获取调用参数 // func_num_args(),func_get_arg(), func_get_args() // 现在已经用不到它们了,我们可以使用一种更加优雅的方式来获取:剩余参数 // 剩余参数的概念与语法与JavaScript中是一样的, 熟悉js的同学一定不陌生 // 计算任意个数据之和 function sum(...$args) { print_r($args); echo '<br>'; return array_sum($args); } $arr = [2, 3, 4, 6, 88, 23, 1, 24]; // ...: 剩余参数展开与收集操作符 // 调用时,执行展开操作, 传参时执行收集操作 echo sum(...$arr); ``` --- ## 5. 回调函数 | 语法 | 类型 | 执行方式 | 应用场景 | | -------- | ------------- | -------- | -------- | | 匿名函数 | 闭包`Closure` | 异步 | 函数参数 | > 异步执行,是指当前函数的执行并不会中断当前程序的执行流程 示例代码: `demo5.php` ```php <?php # 回调函数 $data = range(1, 100); // print_r($data); // 使用回调,可以异步的处理海量数据,并不中断当前程序 $arr1 = array_map(function ($item) { if ($item % 2 === 0) return $item; }, $data); echo '<hr>'; print_r($arr1); // 过滤掉空值 $arr2 = array_filter($arr1, function ($item) { return $item; }); echo '<hr>'; print_r($arr2); ``` --- ## 6. 命名空间 - 使用目录来整理文档, 允许将同名文档,存储在不同的目录下面即可 - 不同目录下的同名文件,访问时必须带上的它的目录名称,以未区别 - 命名空间采用类似的思想,同名函数,只要声明在不同空间中即可 - 同样, 访问这些函数时, 也需要带上它的命名空间才可以 示例代码: `demo6.php` ```php # 函数命名空间 // function demo1() // { // return __FUNCTION__; // } // function demo1() // { // return __FUNCTION__; // } // 报函数重复命名错误 // 可以在不同命名空间中创建同名函数 namespace ns1 { function demo1() { return __FUNCTION__; } } namespace ns2 { function demo1() { return __FUNCTION__; } } namespace { // 带有空间的函数,调用时需要带上它的空间名称 echo \ns1\demo1(); echo '<hr>'; echo \ns2\demo1(); } ```