函数
1. 语法
函数是实现代码复用的重要方式,在所有编程语言中均如此
function 函数名称(类型: 参数列表): 返回值类型
{
// 函数体
return 返回值;
}
序号 | 名称 | 描述 |
---|---|---|
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 (){...} |
也叫”闭包”或”函数表达式”,常用做回调处理 |
// getPrice: 小驼峰命名法
// get_price: 蛇形命名法
//1.自定义函数
function getPrice(float $money, float $discount) : float
{
return $money * $discount;
}
echo '实付金额: ' . getPrice(5000, 0.8);
echo '<hr>';
//2.系统函数
$a =[100,200,300];
//求数组的和
echo array_sum($a);
echo '<hr>';
//3.可变函数
function getName(string $name) : string
{
return $name;
}
$funcName = 'getName';
echo '姓名: ' . $funcName("king");
echo '<hr>';
// 4. 匿名函数: 闭包, 可以访问父作用域的变量
$discount = 0.6;
// $discount 的作用域是全局
$getAmount = function (float $money, int $num) use ($discount) : float
{
$amount = $money * $num;
return $amount >= 2000 ? $amount * $discount : $amount;
};
echo '实付金额: ' . $getAmount(100, 20);
echo '<hr>';
// 如果父作用域又是一个函数
$f = function ($discount) {
// 子函数
return function (float $money, int $num) use ($discount) : float
{
$amount = $money * $num;
return $amount >= 2000 ? $amount * $discount : $amount;
};
};
echo '金额: ' .$f(0.6)(200, 20);
函数如果如果需要使用全局变量,可在
function()
后面使用use(全局变量)
调用
3. 返回值
- 函数必须要有返回值
- 函数必须是遵守单值返回原则
序号 | 场景 | 描述 |
---|---|---|
1 | return |
可以返回任何类型的值,包括函数类型 |
2 | 无return |
遇到} 也会返回, 默认返回null |
- 如果需要返回多个值,可以通过以下手段
序号 | 返回值类型 | 描述 |
---|---|---|
1 | string |
字符串拼接 |
2 | array |
数组 |
3 | json |
JSON 字符串 |
4 | serialize |
序列化字符串 |
json 和序列化,使用时需要进行解码操作
// 1. 字符串拼装
function getName(string $name) : string
{
$names = $name;
$label = '姓名';
return $label .': ' . $name;
}
echo getName();
echo '<hr>';
// 适合处理大量的php+html混写
// 这种返回的格式是用户自定义的,前端处理非常麻烦
// 2.数组
function getStatus(){
return ['status'=>1, 'message'=>'成功'];
}
$res = print_r(getStatus(), true);
//格式化输出
printf('<pre>%s</pre>', $res);
echo getStatus()['status'] == 1 ? '<span style="color:green">'.getStatus()['message']. '</span>' : '验证失败';
echo '<hr>';
// 3.json 字符串
// json: 是用js对象字面量的方式来表示数据,是一种轻量级通用的数据交换或传输格式
// json本质上就是一个具有一定结构和格式的字符串, 不过这种格式得到了公认,几乎所有编程语言都有支持它的接口
function getStatus() : string
{
// json_encode(): 将php数据编码为json格式的字符串返回
return json_encode(['status'=>1, 'message'=>'成功']);
}
$data = getStatus();
echo $data;
// 将json格式的字符串还原/解析为php对象/数组
$var = json_decode($data, true);
print_r($var);
echo '<hr>';
// 4. 通过序列化返回多个值
// 其实json也是一种序列化
function getStatus() : string
{
return serialize(['status'=>1, 'message'=>'成功']);
}
echo getStatus();
// 反序列化才可以使用
$arr =unserialize(getStatus());
printf('<pre>%s</pre>', print_r($arr,true));
4. 参数
- 调用者可以通过参数将数据传递到函数中
- 参数是以逗号分隔的表达式列表
- 参数按照从左到右的顺序求值
参数类型
序号 | 类型 | 描述 |
---|---|---|
1 | 值参数 | 默认传参方式 |
2 | 引用参数 | 改变原始调用参数值 |
3 | 默认参数 | 调用时允许省略的参数 |
4 | 剩余参数 | 调用参数数量不确定 |
// 1. 值参数, 默认
function demo1(float $a,float $b) : float
{
return "$a + $b=".$a+$b;
}
$a=5;$b=10;
echo demo1($a,$b) , '<br>';
// 在函数中改变了调用参数的值,但原始调用参数并没有发生变化
echo $a+$b;
echo '<hr>';
// 2. 引用传递
function demo2(float &$a,float $b) : float
{
return $a +=$b;
}
$a = 100;
$b = 20;
echo demo2($a,$b) , '<br>';//值200
// 如果在参数前面使用了取地址符,则会改变原始调用参数的值
echo $a; //值200
echo '<hr>';
// 3. 默认参数
// 默认参数必须写在必选参数的后面
//将$c设置为默认参数初始值为100
function demo3($a,$b,$c=100)
{
return $a+$b+$c;
}
//当demo3的第三个参数未设置时$c的值为100,所以结果为103
echo demo3(1,2).'<br>';
//也可设置默认参数的值,此时$c的值为10,所以结果为13
echo demo3(1,2,10).'<hr>';
// 4. 剩余参数
function demo4(float $a, float $b, float $c ) : float
{
return $a + $b + $c;
}
// 计算三个数之和
echo demo4(1,2,3), '<br>';
echo '<hr>';
//第一种方法
function demo5( )
{
// 参数数量
// return func_num_args();
// 根据索引返回指定的调用参数
// return func_get_arg(2);
$total = 0;
// for ($i = 0;$i <func_num_args(); $i++ ) {
// $total +=func_get_arg($i);
// }
// return $total;
foreach (func_get_args() as $value) {
$total +=$value;
}
return $total;
}
// echo demo5(3,4,7,8,24);
print_r(demo5(3,4,7,8,24));
echo '<hr>';
//第二种方法
$arr=[1,2,3,4,5,6,7,8,9,100];
//'...'将传入的参数打包成数组
function demo5(...$arr)
{
return array_sum($arr);
}
// ...:
// 1. 用在函数的形式参数列表中,表示"收集",将多个离散的参数打包到一个数组中处理
// 2. 用在函数的调用参数列表中,表示"展开",还原将一个数组展开成一个个离散的值
print_r(demo5(...$arr));
echo '<hr>';
// 扩展知识
$user[] = [100, 'admin', 90];
$user[] = [110, 'peter', 60];
$user[] = [120, 'jack', 98];
// 数组解包
// js中解构赋值, php中也有解构
foreach ($user as list($id, $name)) {
printf('id=%s, name=%s<br>', $id, $name);
}
5. 回调函数
语法 | 类型 | 执行方式 | 应用场景 |
---|---|---|---|
匿名函数 | 闭包Closure |
异步 | 函数参数 |
异步执行,是指当前函数的执行并不会中断当前程序的执行流程
php中提供了两个内置的回调函数call_user_func()
call_user_func_array()
。
这两个函数的区别是:
call_user_func_array(回调函数,参数数组)
是以数组的形式接受回调函数和参数的。
call_user_func(回调参数, 参数1, 参数2)
参数的个数是根据回调函数来决定的。
//普通函数
function f1($param1,$param2)
{
echo '函数'.__FUNCTION__.'被执行,传入的参数是:'.$param1.' '.$param2;
echo "<br/>";
}
//通过call_user_func调用函数f1
call_user_func('f1','姓名','king');
//通过call_user_func_array调用函数
call_user_func_array('f1',array('姓名','wen'));
//结果
函数f1被执行,传入的参数是:姓名 king
函数f1被执行,传入的参数是:姓名 wen
class A{
public $name;
function show($param)
{
echo '传入参数是:'.$param."<br/>";
echo 'my name is:'.$this->name;
echo "<br/>";
}
function show1($param1,$param2)
{
echo __METHOD__.'方法被执行,传入参数是:'.$param1.' '.$param2."<br/>";
}
public static function show2($param1,$param2)
{
echo __METHOD__.'方法被执行,传入参数是:'.$param1.' '.$param2."<br/>";
}
}
//调用类中非静态成员函数,该成员函数中有$this调用了对象中的成员
$a = new A;
$a->name = 'wen';
call_user_func_array(array($a,'show',),array('han!'));
//调用类中非静态成员函数,没有对象被创建,该成员函数中不能有$this
call_user_func_array(array('A','show1',),array('han!','wen'));
//调用类中静态成员函数
call_user_func_array(array('A','show2'),array('param1','param2'));
//运行结果
传入参数是:han!
my name is:wen
A::show1方法被执行,传入参数是:han! wen
A::show2方法被执行,传入参数是:param1 param2
6. 命名空间
- 使用目录来整理文档, 允许将同名文档,存储在不同的目录下面即可
- 不同目录下的同名文件,访问时必须带上的它的目录名称,以未区别
- 命名空间采用类似的思想,同名函数,只要声明在不同空间中即可
- 同样, 访问这些函数时, 也需要带上它的命名空间才可以
PHP如何定义命名空间
默认情况下,所有常量、类和函数名都放在全局空间下,就和PHP支持命名空间之前一样。
命名空间通过关键字namespace 来声明。如果一个文件中包含命名空间,它必须在其它所有代码之前声明命名空间。语法格式如下;
<?php
// 定义代码在 'MyProject' 命名空间中
namespace MyProject;
// ... 代码 ...
也可以在同一个文件中定义不同的命名空间代码,如:
<?php
namespace MyProject1;
// MyProject1 命名空间中的PHP代码
namespace MyProject2;
// MyProject2 命名空间中的PHP代码
// 另一种语法
namespace MyProject3 {
// MyProject3 命名空间中的PHP代码
}