2025 PHP7/8 实战入门:15 天精通现代 Web 开发——第 4 课:函数基础

PHP 函数基础详解与实战

第 4 课:函数基础

一、学习目标

  1. 掌握 PHP 函数的声明、调用与参数传递规则
  2. 熟练运用 PHP7 返回值类型声明与 PHP8 命名参数特性
  3. 理解变量作用域及匿名函数的使用场景
  4. 能够编写高可读性、高兼容性的函数代码

二、核心知识点

(一)函数的基本结构
  1. 函数声明语法(PHP7/8 延续基础结构,新增类型增强)

    <?php
    // 基础函数结构:关键字+函数名+参数列表+函数体
    function 函数名(参数1, 参数2, ...): 返回值类型 {
        // 函数体代码
        return 返回值; // 与返回值类型匹配
    }
    
    // 无参数、无返回值示例
    function showWelcome(): void { // void表示无返回值(PHP7+支持)
        echo "欢迎学习PHP函数!<br>";
    }
    
    // 调用函数
    showWelcome();
    ?>
    
  2. 函数命名规范

    • 以字母或下划线开头,可包含字母、数字、下划线
    • 区分大小写(但推荐统一用小写 + 下划线命名法,如get_user_info
    • 避免使用 PHP 内置函数名(如echoarray等)
  3. 函数的优势

    • 代码复用:避免重复编写相同逻辑
    • 模块化:将复杂功能拆分为独立函数,便于维护
    • 可读性:通过函数名直观理解功能,降低代码复杂度
(二)函数参数进阶
  1. 参数默认值(PHP7/8 无变化,需注意默认参数位置)

    • 默认参数必须放在非默认参数之后
    • 默认值只能是常量(不能是变量、函数调用等)

    示例:

    <?php
    // 正确:默认参数在最后
    function getMessage(string $name, string $type = "info"): string {
        return "[{$type}] 欢迎您,{$name}!";
    }
    
    // 调用函数
    echo getMessage("张三"); // 使用默认值"info",输出:[info] 欢迎您,张三!
    echo getMessage("李四", "warning"); // 自定义类型,输出:[warning] 欢迎您,李四!
    
    // 错误:默认参数不能在非默认参数之前
    // function getMessage(string $type = "info", string $name): string { ... }
    ?>
    
  2. PHP7 标量类型声明(参数类型约束)

    • 支持标量类型:intstringfloatbool
    • 配合declare(strict_types=1)实现严格类型检查

    示例:

    <?php
    declare(strict_types=1); // 严格模式(必须放在文件第一行)
    
    // 参数指定为int类型,返回值也指定为int类型
    function add(int $a, int $b): int {
        return $a + $b;
    }
    
    echo add(2, 3); // 正确:输出5
    // echo add(2.5, 3.5); // 错误:严格模式下不允许float转int
    // echo add("2", "3"); // 错误:严格模式下不允许string转int
    ?>
    
  3. PHP8 命名参数(革命性特性,简化参数传递)

    • 调用函数时可通过 “参数名 = 值” 的方式传递参数,无需按顺序
    • 适合参数较多且有默认值的场景,提升代码可读性

    示例:

    <?php
    // 多参数函数(含默认值)
    function createUser(
        string $name,
        string $email,
        int $age = 18,
        string $role = "user"
    ): array {
        return [
            "name" => $name,
            "email" => $email,
            "age" => $age,
            "role" => $role
        ];
    }
    
    // 传统调用(必须按顺序,如需跳过默认参数需传null)
    $user1 = createUser("张三", "zhangsan@example.com", 20, "admin");
    
    // PHP8命名参数(可打乱顺序,跳过默认参数)
    $user2 = createUser(
        name: "李四",
        email: "lisi@example.com",
        role: "admin" // 跳过age,使用默认值18
    );
    
    print_r($user2);
    // 输出:Array ( [name] => 李四 [email] => lisi@example.com [age] => 18 [role] => admin )
    ?>
    
  4. 可变参数(不定长参数)

    • ...表示,接收任意数量的参数,自动转为数组
    • PHP7/8 支持在函数参数和调用时使用

    示例:

    <?php
    // 计算任意数量数字的总和
    function sum(int ...$numbers): int {
        $total = 0;
        foreach ($numbers as $num) {
            $total += $num;
        }
        return $total;
    }
    
    echo sum(1, 2, 3); // 输出6
    echo sum(10, 20, 30, 40); // 输出100
    
    // 调用时展开数组(PHP7+)
    $arr = [5, 6, 7];
    echo sum(...$arr); // 等价于sum(5,6,7),输出18
    ?>
    
(三)变量作用域与闭包
  1. 变量作用域分类

    • 局部变量:函数内部定义,仅在函数内有效
    • 全局变量:函数外部定义,需通过global关键字或$GLOBALS数组在函数内访问
    • 超全局变量:PHP 预定义的全局变量(如$_GET$_POST),可在任何作用域直接访问

    示例:

    <?php
    $global_var = "全局变量"; // 全局变量
    
    function testScope() {
        $local_var = "局部变量"; // 局部变量
        
        // 方法1:通过global关键字访问全局变量
        global $global_var;
        echo "通过global访问:{$global_var}<br>";
        
        // 方法2:通过$GLOBALS数组访问全局变量(PHP7/8推荐)
        echo "通过\$GLOBALS访问:{$GLOBALS['global_var']}<br>";
        
        echo "局部变量:{$local_var}<br>";
    }
    
    testScope();
    // echo $local_var; // 错误:局部变量在函数外不可访问
    
    // 超全局变量(无需声明,直接访问)
    echo "当前脚本文件名:{$_SERVER['PHP_SELF']}";
    ?>
    
  2. 静态变量(static)

    • 函数内用static声明,函数执行后值不丢失(保留上次执行结果)
    • 常用于计数、缓存等场景

    示例:

    <?php
    function countVisit(): int {
        static $count = 0; // 静态变量,仅初始化一次
        $count++;
        return $count;
    }
    
    echo "第" . countVisit() . "次访问<br>"; // 输出:第1次访问
    echo "第" . countVisit() . "次访问<br>"; // 输出:第2次访问
    echo "第" . countVisit() . "次访问<br>"; // 输出:第3次访问
    ?>
    
  3. 匿名函数(闭包)

    • 没有名称的函数,可作为变量赋值或函数参数
    • PHP7/8 支持use关键字引入外部变量(解决作用域问题)

    示例:

    <?php
    // 1. 匿名函数作为变量赋值
    $greet = function(string $name): string {
        return "Hello, {$name}!";
    };
    
    echo $greet("PHP8"); // 输出:Hello, PHP8!
    
    // 2. 匿名函数作为函数参数(配合array_map等函数)
    $numbers = [1, 2, 3, 4];
    // 将数组中每个元素乘以2(用匿名函数作为回调)
    $doubled = array_map(function(int $num): int {
        return $num * 2;
    }, $numbers);
    
    print_r($doubled); // 输出:Array ( [0] => 2 [1] => 4 [2] => 6 [3] => 8 )
    
    // 3. 用use引入外部变量
    $factor = 3;
    $tripled = array_map(function(int $num) use ($factor): int {
        return $num * $factor; // 使用外部变量$factor
    }, $numbers);
    
    print_r($tripled); // 输出:Array ( [0] => 3 [1] => 6 [2] => 9 [3] => 12 )
    ?>
    
(四)函数高级特性
  1. 返回值类型声明(PHP7+)

    • 函数声明时用:指定返回值类型,强制函数返回对应类型的值
    • 支持void(无返回值)、self(返回当前类实例)等特殊类型

    示例:

    <?php
    declare(strict_types=1);
    
    // 返回值为string类型
    function getUserName(int $user_id): string {
        $users = [1 => "张三", 2 => "李四"];
        return $users[$user_id] ?? "未知用户";
    }
    
    // 返回值为array类型
    function getUserList(): array {
        return [
            ["id" => 1, "name" => "张三"],
            ["id" => 2, "name" => "李四"]
        ];
    }
    
    // 无返回值(void)
    function logMessage(string $message): void {
        file_put_contents("log.txt", $message . "\n", FILE_APPEND);
    }
    ?>
    
  2. PHP8 属性提升(构造函数简化)

    • 虽然属于类特性,但常与类的成员函数结合使用
    • 可在构造函数参数前加访问修饰符(public/private等),自动生成类属性

    示例:

    <?php
    class User {
        // PHP8构造函数属性提升:参数自动转为类属性
        public function __construct(
            public int $id,
            public string $name,
            public string $email
        ) {
            // 无需额外赋值,PHP自动处理
        }
        
        // 类的成员函数
        public function getInfo(): string {
            return "ID: {$this->id}, 姓名: {$this->name}, 邮箱: {$this->email}";
        }
    }
    
    $user = new User(1, "张三", "zhangsan@example.com");
    echo $user->getInfo(); // 输出:ID: 1, 姓名: 张三, 邮箱: zhangsan@example.com
    ?>
    

三、注意事项

  1. 参数传递陷阱

    • 基本类型(int、string 等)默认按值传递(函数内修改不影响外部变量)
    • 复合类型(array、object 等)默认按引用传递(函数内修改会影响外部变量)
    • 如需按引用传递基本类型,需在参数前加&(如function modify(&$num) { ... }
  2. 函数嵌套问题

    • 避免过度嵌套函数(函数内定义函数),会导致代码可读性差
    • 如需复用嵌套逻辑,建议拆分为独立函数或使用匿名函数
  3. 版本兼容性

    • 命名参数仅 PHP8 + 支持,低版本需按顺序传递参数
    • void返回值类型仅 PHP7.1 + 支持,低版本可省略返回值声明
    • 构造函数属性提升仅 PHP8 + 支持,低版本需手动定义类属性并赋值

四、实战练习

  1. 创建day4文件夹,新建math_utils.php文件:

    • 定义一个MathUtils类,包含以下静态函数:
      • sum(int ...$numbers): int:计算任意数量整数的总和
      • average(float ...$numbers): float:计算任意数量浮点数的平均值(保留 2 位小数)
      • maxValue(array $arr): int|float:返回数组中的最大值(支持整数和浮点数混合)
    • 使用 PHP7 类型声明和返回值类型,PHP8 命名参数调用函数
    • 编写测试代码,验证每个函数的正确性
  2. 新建user_service.php文件:

    • 定义一个UserService类,包含以下方法:
      • getUserById(int $id): array:根据 ID 获取用户信息(模拟数据:ID 为 1 返回张三,2 返回李四,其他返回空数组)
      • filterUsers(array $users, callable $callback): array:接收用户数组和匿名函数,返回符合条件的用户
    • 调用filterUsers方法,用匿名函数筛选出年龄≥20 的用户(模拟用户数据包含age字段)
    • 使用static变量实现用户查询缓存(同一 ID 多次查询仅返回一次数据)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Anson Jiang

感谢客官老爷打赏的咖啡钱:-)

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值