函数知识总结
1. 语法
- 功能:函数是实现代码复用的重要方式,在所有编程语言中均如此
//函数声明
function 函数名称(类型: 参数列表): 返回值类型
{
// 函数体
return 返回值;
//隐式:结束大括号的时候自动返回
//return不是必须的
}
//函数调用,按照函数名称调用(调用需要echo)
序号 | 名称 | 描述 |
---|---|---|
1 | function |
声明函数 |
2 | 函数名称 |
符合 PHP 标识符命名规范,不区分大小写 |
2 | 参数列表 |
零个或多个接收外部传入到函数的变量 |
2 | {... |
创建出一个封闭的函数作用域 |
2 | 函数体 |
由零个可多个合法的 PHP 语句组成 |
2 | return 值 |
将执行结果返回函数调用者[可选] |
2 | ...} |
函数执行结束,如果没有return ,则返回null |
2. 类型
序号 | 类型 | 语法 | 描述 |
---|---|---|---|
1 | 自定义函数 | function getName(){...} |
用户根据业务需求创建 |
2 | 系统函数 | substr(), count()... |
也叫预定义函数,不必声明直接调用 |
3 | 可变函数 | $funcName(); |
函数名使用变量表示 |
4 | 匿名函数 | $f = function (){...} |
也叫”闭包”或”函数表达式”,常用做回调处理 |
2.1 自定义函数(命名函数)
- 1.getPrice: 小驼峰命名法
- 2.get_price: 蛇形命名法
<?php
function myPrice(int $num, int $price): int
{
$myPrice = $num * $price;
return $myPrice;
}
echo myPrice(20, 30);
2.2 系统函数
- 系统开启 php 自带的
<?php
$str = '我爱php中文网';
echo mb_substr($str, 0, 3);
//系统函数,自带的,不需自定义
2.3 可变函数
- 函数名储存在变量中
- 通过变量名调用函数
<?php
function myPrice(int $num, int $price): int
{
$myPrice = $num * $price;
return $myPrice;
}
echo myPrice(20, 30);
echo '<hr>';
//可变函数
// 函数名储存在变量中
$funcName = 'myPrice';
echo $funcName(20, 30);
//通过变量调用函数
2.4 匿名函数
- 闭包可以访问父作用域(use)
<?php
// 4.匿名函数:闭包
$discount = 0.6;
$num = 100; //全局变量
//闭包就是匿名函数,被赋值给一个变量了,闭包可以访问父作用域
$getPrice = function (float $num, float $price) use ($discount): float {
// global $discount;
$myprice = $num + $price;
return $myprice > 100 ? $myprice * $discount : $myprice;
};
echo $getPrice(100, 20);
- 函数中又有一个函数(相互嵌套)
<?php
// 如果父作用域又是一个函数
$discount = 0.6;
$a = function ($discount) {
//子函数
$getPrice = function (float $num, float $price) use ($discount): float {
$myprice = $num + $price;
return $myprice > 100 ? $myprice * $discount : $myprice;
};
return $getPrice;
};
echo $a(0.6)(200, 20);
// echo gettype($a);
3. 返回值
- 函数必须要有返回值
- 函数必须是遵守单值返回原则
返回多值需要处理:1.字符串拼装,2.数组,3.jason 字符串,4.序列化:字符串
| 序号 | 场景 | 描述 |
| —— | ————— | ————————————————- |
| 1 |return
| 可以返回任何类型的值,包括函数类型 |
| 2 | 无return
| 遇到}
也会返回, 默认返回null
|如果需要返回多个值,可以通过以下手段
序号 | 返回值类型 | 描述 |
---|---|---|
1 | string |
字符串拼接 |
2 | array |
数组 |
3 | json |
JSON 字符串 |
4 | serialize |
序列化字符串 |
json 和序列化,使用时需要进行解码操作
java 等多个地方使用
3.1 字符串拼接
- 适合处理大量 php+html 代码混合
- 返回格式为用户自定义,前端处理非常麻烦
<?php
function demo1(): string
{
$status = '1';
$message = '登陆成功';
return $status . '状态为:' . $message;
}
echo demo1();
//适合处理大量php+html代码混合
//返回格式为用户自定义,前端处理非常麻烦
3.2 通过数组的方式
- 是一种使用 js 字面量的方式来表示数据,是一种轻量级别的通用的数据交换或者传输格式;
- jason 本质上就是一个具有一定结构和格式的字符串,几乎所有编程语言都有他的接口;
<?php
// 返回值通过数组
//函数是全局的
function demo2(): array
{
// $status = '1';
// $message = '登陆成功';
return ['status' => 1, 'message' => '成功'];
}
// echo print_r(demo2(), true);
// echo '<pre>' . print_r(demo2(), true) . '</pre>';
printf('<pre> %s </pre>', print_r(demo2(), true));
// echo demo2()['status'] == 1 ? demo2()['message'] : '验证失败';
echo demo2()['status'] == 1 ? '<span style="color:red">' . demo2()['message'] . '</span> ' : '验证失败';
3.3 通过 json 的方式
- 将 php 数据编码为 json 格式来返回
<?php
function demo3(): string
{
//json_encode():将php数据编码为json格式来返回
return json_encode(['status' => 1, 'message' => '登陆成功']);
}
$data = demo3();
echo $data;
- 将 json 格式的字符串还原/解析为 php 对象或者数组
// - 将 json 格式的字符串还原/解析为 php 对象或者数组
$var = json_decode($data, true);
print_r($var);
3.4 序列化:字符串
- 其实 json 也是一种序列化
- 如何序列化?
<?php
//4.通过序列化返回多个值
function demo4(): string
{
return serialize(['status' => 1, 'message' => '登陆成功']);
//a:2:{s:6:"status";i:1;s:7:"message";s:12:"登陆成功";}
//a数组
//2两个元素
//s字符串
//6个字符
//i值为证书
//1是他的值
//s字符串
//7个字符
//utf8一个汉字3个字节
}
echo demo4();
- 如何反序列化
//反序列化
unserialize(demo4());
$arr = unserialize(demo4());
printf('<pre>%s<pre>', print_r($arr, true));
4. 参数
- 调用者可以通过参数将数据传递到函数中
- 参数是以逗号分隔的表达式列表
- 参数按照从左到右的顺序求值
参数类型
序号 | 类型 | 描述 |
---|---|---|
1 | 值参数 | 默认传参方式 |
2 | 引用参数 | 改变原始调用参数值 |
3 | 默认参数 | 调用时允许省略的参数 |
4 | 剩余参数 | 调用参数数量不确定 |
4.1 值传递,值参数
-在函数中改变了调用参数的值,但是原始调用参数并没有发生变化
//1.值参数,值传递
function demo1(float $arg): float
{
return $arg * 2;
}
$value = 1000;
echo demo1($value), '<br>';
//在函数中改变了调用参数的值,但是原始调用参数并没有发生变化
echo $value;
4.2 引用参数,引用传递
&
取地址符
//2.引用参数,引用传递
function demo1(float &$arg): float
{
return $arg *= 2;
}
$value = 1000;
echo demo1($value), '<br>';
//如果在参数前面使用了取地址符,则会改变原始调用参数的值
echo $value;
echo '<hr>';
4.3 默认参数
- 默认参数不能出现在必选参数前面
<?php
function demo1(float $a, float $b, string $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 demo1(10, 20);
echo demo1(10, 20, '*');
4.4 剩余参数(重点)
return func_num_args();
返回参数的数量return func_get_arg();
根据索引返回指定的调用参数return func_get_args();
返回一个数据,分别是索引对应的值
4.4.1 第一种方式,for 循环
<?php
function demo1()
{
// return func_num_args();
// return func_get_arg(1);
// return func_get_args();
$sum = 0;
for ($i = 0; $i < func_num_args(); $i++) {
$sum += func_get_arg($i);
}
return $sum;
}
print_r(demo1(3, 4, 6, 7, 8, 52, 4,));
4.4.2 第二种方式,foreach 循环
<?php
function demo1()
{
$sum = 0;
// 第二种办法
foreach (func_get_args() as $value) {
$sum += $value;
}
return $sum;
}
print_r(demo1(3, 4, 6, 7, 8, 52, 4,));
4.4.3 剩余参数
...
参数归纳,使用在参数列表中,表示收集,将多个离散的参数打包到一个数组中处理...
调用参数,表示展开/还原一个数组为离散值- 不会限制用户传入数据的数量,功能很强大
//剩余参数
// ...:参数归纳,使用在参数列表中,表示收集,将多个离散的参数打包到一个数组中处理
function demo2(...$args): float
{
// return $args;
return array_sum($args);
// return array_product($args);
}
// ...:调用参数,表示展开/还原一个数组为离散值
$arr = [3, 4, 6, 7];
print_r(demo2(...$arr));
5. 回调函数
语法 | 类型 | 执行方式 | 应用场景 |
---|---|---|---|
匿名函数 | 闭包Closure |
异步 | 函数参数 |
- 回调函数:用在函数的回调参数中
异步执行,是指当前函数的执行并不会中断当前程序的执行流程
<?php
# 回调函数:用在函数的回调参数中
//回调:在将来某一时刻,或者某个事件发生时再执行
//生成一个1-100共100个整数的数组
// $data=[1,2,3,4,5,6,7,8,9,...,100];
// $data = range(0, 99, 5);
// // range(起始数字,结束数字,步长)
// print_r($data);
// 只返回当前数据中偶数
$data = range(0, 99);
// print_r($data);
//只返回偶数
var_dump(4 % 2);
echo ((4 % 2) == 0) ? '偶数' : '奇数';
$res = array_map(function (int $item) {
if ($item % 2 === 0) return $item;
}, $data);
// array_map(回调函数,数组)
echo $res;
printf('<pre?>%s</pre>', print_r($res, true));
- 用在函数的参数中
// 过滤空值/假值
// array_filter仅返回结果为trus的数据
$res = array_filter($res, function ($item) {
return $item;
});
$res = array_values($res);
printf('<pre>%s</pre>', print_r($res, true));
6. 命名空间
- 使用目录来整理文档, 允许将同名文档,存储在不同的目录下面即可
- 不同目录下的同名文件,访问时必须带上的它的目录名称,以未区别
- 命名空间采用类似的思想,同名函数,只要声明在不同空间中即可
- 同样, 访问这些函数时, 也需要带上它的命名空间才可以
目的是为了方式全局成员的命名冲突(全局成员:函数,常量,类,接口)
<?php
# 命名空间(相当于在不同的目录下)
// 防止命名冲突
// 全局成员:函数,常量,类,接口
namespace ns1 {
function demo1(): string
{
return __FUNCTION__;
}
}
namespace ns2 {
function demo1(): string
{
return __FUNCTION__;
}
}
// 全局空间不需要名称
namespace {
echo \ns1\demo1();
echo '<hr>';
echo \ns2\demo1();
}
总结
本节课结束了函数的学习,用一句最经典的话来概括就是:函数是为了代码的共享,和变量的目的是为了数据的共享一致,与此同时函数是一个全局变量,可以在页面的任何位置调用函数,发现 PHP 的真正威力源自于它的函数。