函数
1. 函数的声明与调用
函数是代码复用的重要手段
ps:变量是数据复用的重要手段
函数分类(自定义函数,系统函数(内置函数),可变函数,匿名函数)
/*
函数语法
声明一个函数
function 函数名称的标识符:函数名(参数列表 arguments 形参){
函数体 (逻辑代码)
}
函数调用
函数名(实参);
*/
function sum(int $a, int $b):int
{
return $a + $b;
}
sum(1,6);
- *自定义函数
function comStr(string $a,string $b):string
{
return $a.$b;
}
comStr('盘','古');
- *内置函数
PHP内部封装的函数(针对字符串,数组… 便于开发者使用)
内置函数有很多 记住常用的 其他的心里有个底就好 使用时再具体查看
// 返回数组长度 PHP内置函数 count
$arr1 = [
{'name'=>'盘古','sex'=>'男'},
{'name'=>'女娲','sex'=>'女'}
];
echo count([1,23,4,5]); // 4
echo count($arr1); // 2
// 切割字符串 substr() mb_substr();
// 使用 substr(需要切割的字符串,起始位置,切割长度);
$userName = '世界那么大,我想去看看';
echo substr($userName,0,6); // 世界
echo mb_sbustr($userName,0,6); // 世界那么大,
// 在utf-8编码中 中文占3个字符 在GBK编码中 中文占两个字符 substr() 是根据字符来切割的 所以所得结果不同
- 可变函数
如果一个变量名后有小括号(),那么php就会寻找与变量值同名的函数并执行它。也就是说如果给一个变量赋不同的值,程序就会调用不同的函数
注意,可变函数不能直接用于例如 echo,print,unset,isset,empty,include,require 以及类似的语言结构 需要使用自己包装的函数来将这些结构用作可变函数
function say(){
echo '你好!世界';
}
function hobby(){
echo '我爱打篮球';
}
function eat(){
echo '今天吃了一大碗米饭!';
}
$funName = 'say';
$funName();
// 输出 你好!世界
$funBame = 'hobby';
$funName();
// 输出 我爱打篮球
$funName = 'eat';
$funName();
// 输出 今天我吃了...
- 匿名函数 不具名(在php中也称为闭包)
js闭包: 在父函数中定义的函数 并且一定存在值的引用(js闭包可以访问3个作用域的变量 自己所在的作用域 父级作用域 以及全局作用域)
js 匿名函数不一定是闭包
js 父子级函数 不一定构成闭包 他们之间一定要存在值的引用(内部函数调用外部函数的变量)
PHP 将匿名函数做为闭包
可以访问父作用域中的变量
闭包的作用 扩展作用域 延长作用域链
/*
闭包
函数内部通过 $GLOBALS 访问全局变量
也可以通过 global $con,.... 访问全局变量
可以通过 use(父级变量) 访问父级变量
*/
$con = 0.6;
$fun1 = function(float $price, int $num)use($con):float
{
return $price * $num * $con;
};
$fun1(1366,4);
/*
闭包通过 use() 访问父级变量 并调用子函数
*/
$con = 0.5;
$f1 = function($price)
{
$f2 = function($num)use($price)
{
return $num * $price;
};
$f3 = function($num,$con)use($price)
{
return $num * $price * $con;
};
$arr = ['f2'=>$f2,'f3'=>$f3];
return $arr;
};
echo $f1(1000)['f2'](3).'<br>';
echo $f1(3600)['f3'](3,0.5);
函数总的分为 1.自定义函数(匿名函数,可变函数)和2.系统(内置)函数
2. 函数的返回值
函数必带返回值
函数返回值 通过 return 返回
函数 return 只能返回单值 如果需要返回多个返回值 可以使用 复合类型数据
重点放在多值返回
// PHP关联数组和普通数组的区别
// 1. 普通数组(索引数组)
// 用数字做为键名的数组一般称为索引数组(索引数组的键是整数,一般从0开始)
// 可以通过下标直接访问值
$arr1 = [1,2,3,4,5];
echo $arr1[0]; // 输出 1
// 2. 关联数组
// 关联数组与索引数组区别就是键值上,关联数组的键值是字符串,并且是开发者规定的 形成明确的索引键,形成键值对关系
$arr2 = ['name'=>'cl','age'=>'52'];
echo $arr2['name']; // 输出 cl
- 索引数组
- 关联数组
// 定义一个函数 不写 return 此时 函数会默认返回 NULL
function f(){
echo '123';
}
// 打印结果 先输出 '123' 然后返回 NULL
var_dump(f());
// 函数默认返回 null(如果开发者不自定义返回值的话)
- PHP返回多值的方式
// 1. 通过字符串拼接
// 解决 返回 html与php混编不能返回多值的问题
// 返回给前端后 前端不好操作
function demo1():string
{
$status = 100;
$message = '成功';
return $status.$message;
}
demo1();
// 2. 通过数组返回
function demo2():array
{
$status = 100;
$message = '查询成功';
return ['status'=>$status,'message'=>$message];
}
// echo 不能打印数组
// 只能通过 var_dump() print_r()
demo2();
// 3.通过json js对象字面量的字符串返回多值 通过 json_encode()加码
function demo3():string
{
$status = 100;
$message = '查询成功';
$data = ['status'=>$status,'message'=>$message];
return json_encode($data);
}
// 因为json_encode() 将其他类型的数据转换成字符串 所以此时可以使用 echo 打印 json_encode() 加码的数据
echo demo3(); // 输出{"status":100,"message":"\u67e5\u8be2\u6210\u529f"}
// 通过 json_decode()将 json字符串解码
// 上一步加码的数据为数组 所以解码回来数据会变成json对象 所以不能使用echo
// 不希望解码变成对象 可以在 json.decode()中加入第二个参数 true 返回json数组
var_dump(json_decode(demo3())); // object(stdClass)#1 (2) { ["status"]=> int(100) ["message"]=> string(12) "查询成功" } object
var_demp(json_decode(demo3,true)); // array(2) { ["status"]=> int(100) ["message"]=> string(12) "查询成功" } array
// 前端通过 JSON.parse()可以将json字符串转换成 json数组
// 前端通过 JSON.stringify(); 可以将 其他类型的值 转换成 json字符串
// 前端常用 JSON.parse() 和 JSON.stringify()
// 例如 做本地存储。。。
var user = [];
var data1 = {
name:'cl',
age:18,
hobby:'篮球'
};
user.push(data1);
// 通过 JSON.stringify() 将数组转成 json 字符串存储。
localStorage.users = JSON.stringify(user);
// 通过 JSON.parse(); 将json字符串转换成 json数组
var data1 = JSON.parse(localStorage.users);
console.log(data1);
// 4.序列化方式 (系列化) 任何值 serialize();
// 可以被多种语言调用
serialize('123');
$status = 100;
$message = '查询成功';
$data = ['status'=>$status,'message'=>$message];
echo serialize($data);
$data1 = serialize($data);
// 反序列化 还原
var_dump(unserialize($data1));
3.函数参数
值参数:默认 和变量的值传递类似 修改了其中一个变量不会修改另一个参数
引用参数:引用传参在形参前面加上 &(取地址符)当前实参的别名 并没有创建新的变量 和变量的引用传值一样。此时 参数变成引用传参 将内存地址传到函数内部 函数内部变化了内存地址所指向的变量 所以函数内部改变了变量 外部变量同时发生改变
默认参数: 参数的默认值 即没有传递参数时参数的默认的值 有默认参数的参数应该放在参数列表的最后面
剩余参数: …变量名 …$args 将所有参数整合到参数列表中 剩余参数用在参数列表中称为收集(归纳) 剩余参数用在函数的调用表达式中称为展开(扩展)
// 1.值参数
$price1 = 1200;
function demo1($price){
// return $price = $price * 2;
return $price *= 2;
}
// 值参数不会改变参数本身
echo demo1($price1); // 2400
echo $price1 // 1200
// 2. 引用参数
// 引用参数需要用到 & (取地址符) 当前实参的别名 并没有创建新的变量 和变量的引用传值一样
$price2 = 2000;
fucntion demo2(&$price){
// 函数内部对参数的更新会实时映射到外部实际参数
return $price *= 2;
}
echo demo2($price2); // 4000
echo $price2; // 4000
// 3. 默认参数
// 没有传参时默认的参数的值
// 函数默认的参数应该放在没有默认参数的后面
function moren($n,$price,$con=0.3){
return $n * $price * $con;
}
// 没有传 $con参数 此时会使用$con的默认值 0.3
echo demo3(4,2000);
echo demo3(4,2000,0.5);
// 4.剩余参数
function demo3($a,$b,$c){
return $a + $b + $c;
}
echo demo3(1,2,3);
// 如果不知道参数的具体个数怎么操作呢?
// 参数不固定
// ...变量名 ...$args 将所有参数整合到数组中
// 剩余参数 用在 函数的参数列表中 称为收集(归纳)
// 将剩余参数用在函数的调用表达式中,是扩展
// 收集
function demo4(...$args){
return array_num($args);
}
var_dump(demo5(1,2,3,4,5,6,7,8,9));
echo demo5(1,2,3,4,5,6,7,8,9);
// echo demo5(...$arr);
// 扩展
// 将剩余参数放到 调用 函数表达式中
$arr = [1,23,4,5,6];
echo demo5(...$arr);
// 前面参数固定 后面参数不固定的情况
function demo5($price,...$args){
$data = ['price'=>$price,'other'=>array_sum($args)];
return $data;
}
print_r(demo5(1000,1,23,4,5,6,7));
// Array ( [price] => 1000 [other] => 46 )
4.回调函数
回调函数,匿名函数,闭包(在PHP中这三个是一样的)
回调函数 常用于异步编程中的参数
异步编程:(对于函数的执行时间,无法预测 通过事件通过回调唤醒主程序)
$data = range(1,100);
// print_r($data);
// 取出 偶数 (除数除2余0的为偶数)
// array_map() 函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组
// array_map(回调,作用数组);
$arr = array_map(function($item){
//echo $item;
if($item % 2 === 0){
return $item;
}
},$data);
//print_r($arr);
//过滤空值
// array_filter()
// array_filter(作用数组,回调函数)
// 用回调函数过滤数组中的元素
// 该函数把输入数组中的每个键值传给回调函数。如果回调函数返回 true,则把输入数组中的当前键值返回给结果数组。数组键名保持不变
$arr1 = array_filter($arr,function($item){
// 返回为true的值 空值 为false 所以直接 返回 $item
// 返回条件为真的数据 空值为false 但 用在判断表达式中 空值也能返回true
// return $item == '';
return $item;
});
//print_r($arr1);
// 数组重排 array_keys() array_values()
$arr1 = array_values($arr1);
print_r($arr1);
// 当处理的数据为动态的 需要使用回调的方式处理结果(不会产生阻塞)
5. 函数命名空间
- 函数也属于全局成员 会存在同一个作用域不能重复定义的问题
- 解决办法 => 函数命名空间
- 命名空间解决全局成员命名冲突问题
- 公共函数库会使用到函数命名空间
namespace ns1{
function demo1(){
return 'demo1';
}
// 同一个作用域 不能重复定义相同的全局变量
// function demo1(){
// return 'demo2';
// }
echo 'ns2';
echo \ns2\demo1();
}
namespace ns2{
function demo1(){
return 'demo2';
}
echo \ns1\demo1();
echo demo1();
echo '<hr>';
}
namespace {
// 全局命名空间
echo \ns2\demo1();
echo \ns1\demo1();
echo '<hr>';
echo ns1\demo1();
echo ns2\demo1();
}
// 当前脚本使用了命名空间 则所有代码必须放在命名空间内
// fucntion demo1(){
// return 'demo1';
// }