第五章-PHP函数

时间:2025-03-17 10:38:38

PHP函数

一,函数的基本概念

函数(Function)是 PHP 中用于封装可重用代码的核心工具。通过函数,可以将复杂逻辑模块化,提高代码的可读性、复用性和可维护性。

一、函数的定义与语法

1. 基本语法

PHP 函数通过 function 关键字定义,语法如下:

function 函数名(参数1, 参数2 = 默认值, ...): 返回类型 {
    // 逻辑代码
    return; // 可选
}

示例

function add(int $a, int $b = 10): int {
    return $a + $b;
}
echo add(5);      // 输出 15 (5 + 10)
echo add(3, 7);   // 输出 10 (3 + 7)
2. 关键组成部分
  • 参数
    • 支持默认值(如 $b = 10)。
    • 可指定类型(如 int $a,PHP 7+ 支持标量类型声明)。
  • 返回值
    • 使用 return 返回结果,若未指定则默认返回 null
    • PHP 7+ 支持返回类型声明(如 : int)。
3. 匿名函数(闭包)

匿名函数没有名称,常用于回调或赋值给变量:

$greet = function($name) {
    echo "Hello, $name!";
};
$greet("Alice"); // 输出:Hello, Alice!
4. 箭头函数(PHP 7.4+)

简化匿名函数语法,自动捕获外部变量:

$multiplier = 2;
$double = fn($x) => $x * $multiplier;
echo $double(5); // 输出:10

二、函数的命名规范

良好的命名规范能显著提升代码可读性。以下是 PHP 函数的常见命名规则:

1. 命名风格
  • 驼峰式(camelCase)

    function getUserData() { ... }
    
  • 下划线式(snake_case)(传统风格):

    function get_user_data() { ... }
    
2. 命名原则
  • 清晰表达功能
    函数名应明确描述其作用,如 calculateTotalPrice()

  • 使用动词
    函数通常表示一个动作,如 createUser()validateEmail()

  • 布尔函数
    ishascan 开头,返回布尔值:

    function isValidEmail($email): bool { ... }
    
3. 避免的命名
  • 无意义名称:如 doSomething()process()
  • 与内置函数冲突:如 array()echo()

三、函数的调用与作用域

1. 调用方式
  • 直接调用:

    echo add(3, 5);
    
  • 动态调用(可变函数):

    $funcName = "add";
    echo $funcName(3, 5); // 等同于 add(3, 5)
    
2. 变量作用域
  • 局部变量:函数内部定义的变量仅在函数内有效。

  • 全局变量:需通过 global$GLOBALS 访问:

    $globalVar = 100;
    function showGlobal() {
        global $globalVar;
        echo $globalVar; // 输出 100
    }
    

四、最佳实践

  1. 单一职责原则
    一个函数只完成一个任务。

    // 错误示例:混合功能
    function processUser($data) {
        validate($data);
        saveToDatabase($data);
        sendEmail($data);
    }
    
    // 正确示例:拆分功能
    function validateUser($data) { ... }
    function saveUser($data) { ... }
    
  2. 参数与返回值

    • 参数尽量不超过 3 个,复杂数据可用数组或对象封装。
    • 使用类型声明(PHP 7+)提升代码健壮性。
  3. 错误处理

    • 验证输入参数,避免函数内部崩溃。
    function divide(int $a, int $b): float {
        if ($b === 0) {
            throw new InvalidArgumentException("除数不能为0");
        }
        return $a / $b;
    }
    

五、总结

核心要点 说明
定义语法 function 函数名(参数): 返回类型 { ... }
命名规范 动词开头,清晰表达功能(如 calculateTotal()
参数与返回值 类型声明、默认值、异常处理
作用域管理 局部变量、全局变量、闭包捕获

二,实际参数与形式参数

在 PHP 函数中,**形式参数(形参)实际参数(实参)**是函数参数传递的两个核心概念。它们的区别与联系直接决定了函数如何接收和处理数据。


1. 形式参数(Formal Parameters)

  • 定义
    形式参数是函数定义时声明的参数,用于接收外部传入的值,是函数内部的局部变量。
  • 位置
    出现在函数声明的小括号中,例如 function sum($a, $b) 中的 $a$b
  • 作用
    • 作为占位符,定义函数需要接收的数据类型和数量。
    • 仅在函数体内有效,与外部变量无关(除非使用引用传递)。

示例

function calculateTotal($price, $quantity) { // $price 和 $quantity 是形式参数
    return $price * $quantity;
}

2. 实际参数(Actual Parameters)

  • 定义
    实际参数是函数调用时传递的具体值或变量,用于为形式参数提供实际数据。
  • 位置
    出现在函数调用的小括号中,例如 sum(3, 5) 中的 35
  • 作用
    • 将外部数据传递给函数。
    • 可以是字面量(如数字、字符串)、变量或表达式。

示例

$itemPrice = 100;
$itemCount = 2;

// 调用 calculateTotal 函数,传递实际参数
$total = calculateTotal($itemPrice, $itemCount); 
// $itemPrice 和 $itemCount 是实际参数

3. 关键区别与联系

特性 形式参数 实际参数
定义位置 函数声明时定义 函数调用时传递
作用域 仅在函数体内有效 可以是全局变量或局部变量
数据来源 由实际参数赋值 来自函数外部
生命周期 函数执行时创建,结束后销毁 独立于函数存在

4. 参数传递方式

PHP 默认采用按值传递,但也可通过引用传递修改外部变量。

  1. 按值传递(默认):

    • 形式参数是实际参数的副本,函数内修改不影响外部变量。
    function increment($num) {
        $num++;
        echo "函数内: $num"; // 输出 6
    }
    
    $value = 5;
    increment($value);
    echo "函数外: $value";   // 输出 5(未改变)
    
  2. 按引用传递

    • 使用 & 符号,形式参数与实际参数指向同一内存地址,函数内修改会影响外部变量。
    function incrementRef(&$num) {
        $num++;
    }
    
    $value = 5;
    incrementRef($value);
    echo $value; // 输出 6
    

5. 默认参数与可变参数

  1. 默认参数
    形式参数可设置默认值,调用时若未传递实参则使用默认值。

    function greet($name = "Guest") {
        echo "Hello, $name!";
    }
    
    greet();          // 输出:Hello, Guest!
    greet("Alice");   // 输出:Hello, Alice!
    
  2. 可变参数(可变长度参数列表)
    使用 ...func_get_args() 接收任意数量的实参。

    // PHP 5.6+ 使用 ... 语法
    function sum(...$numbers) {
        return array_sum($numbers);
    }
    echo sum(1, 2, 3); // 输出 6
    

6. 类型约束(PHP 7+)

形式参数可指定类型,强制实参必须匹配类型,提升代码健壮性:

function divide(int $a, int $b): float {
    if ($b === 0) {
        throw new InvalidArgumentException("除数不能为0");
    }
    return $a / $b;
}

echo divide(10, 3); // 输出 3.333...
// divide("10", 3); // 类型错误:期望 int,传递了字符串

总结

  • 形式参数是函数定义的“占位符”,决定函数如何接收数据。
  • 实际参数是调用函数时传递的具体数据,决定函数处理的内容。
  • 按值传递按引用传递决定了数据修改是否影响外部变量。
  • 类型约束默认参数可增强代码的可靠性和灵活性。

三,参数处理

PHP 函数参数处理是编写灵活且健壮代码的核心技能之一。以下是 PHP 中参数处理的主要方式、规则及最佳实践:


1. 参数传递方式

PHP 支持两种参数传递方式:

按值传递(默认)
  • 特点:函数内部修改参数不会影响外部变量。

  • 定义与使用

    • 语法:在函数定义时为参数指定默认值,调用时若未传递该参数则使用默认值。

      function greet($name = "Guest") {
          echo "Hello, $name!";
      }
      greet();        // 输出:Hello, Guest!
      greet("Alice"); // 输出:Hello, Alice!
      
  • 规则与限制

    1. 参数顺序
      默认参数必须放在非默认参数之后,否则会导致语法错误。

      // 正确:默认参数在后
      function example($a, $b = 2, $c = 3) { /* ... */ }
      
      // 错误:非默认参数在默认参数之后
      function wrong($a = 1, $b) { /* ... */ } // 编译错误
      
    2. 灵活调用
      PHP 8.0+ 支持命名参数,允许跳过中间参数直接为指定参数赋值。

      example(1, c: 5); // PHP 8.0+:$a=1, $b=2(默认), $c=5
      
按引用传递
  • 特点:通过 & 符号声明参数,函数内部修改直接影响外部变量。

  • 定义与使用

    • 语法:在参数前添加 &,使函数内部修改直接影响外部变量。

      function increment(&$num) {
          $num++;
      }
      
      $value = 5;
      increment($value);
      echo $value; // 输出:6
      
  • 规则与限制

    1. 实参必须为变量
      引用传递要求实参必须是已定义的变量,不能是字面量或表达式结果。

      increment(5);       // 错误:Cannot pass literal as reference
      increment($x + 1);  // 错误:表达式结果无法传递
      
    2. 默认值与引用冲突
      引用参数无法设置字面量默认值,因为引用必须绑定到变量。

      // 错误示例
      function refWithDefault(&$var = 10) { /* ... */ } // 编译错误
      

2. 默认参数值

为参数设置默认值,调用时可选传递:

语法规则
  • 默认参数必须放在参数列表末尾。

  • 正确示例

    function greet($name = "Guest", $greeting = "Hello") {
        echo "$greeting, $name!";
    }
    greet(); // 输出:Hello, Guest!
    
  • 错误示例

    function errorExample($a = 1, $b) {} // 编译错误:非默认参数在默认参数后
    
PHP 8+ 命名参数

允许跳过中间参数,直接指定参数名赋值:

greet(greeting: "Hi"); // 输出:Hi, Guest!

3. 可变数量参数

处理不确定数量的参数输入:

传统方式(PHP 5.5 及以下)

使用 func_get_args() 获取参数数组:

function sum() {
    $args = func_get_args();
    return array_sum($args);
}
echo sum(1, 2, 3); // 输出 6
可变参数语法(PHP 5.6+)

使用 ... 操作符:

function sum(...$numbers) {
    return array_sum($numbers);
}
echo sum(1, 2, 3); // 输出 6
类型约束可变参数

限制可变参数的类型:

function sumInts(int ...$numbers) {
    return array_sum($numbers);
}
sumInts(1, 2, "3"); // "3" 转换为整数 3

4. 类型声明(PHP 7+)

增强参数和返回值的类型安全:

标量类型约束
  • 支持 int, string, float, bool 等类型。

    function add(int $a, int $b): int {
        return $a + $b;
    }
    echo add(2, 3);   // 输出 5
    echo add("2", 3); // 字符串 "2" 转换为整数 2
    
严格模式

在文件顶部声明 declare(strict_types=1); 强制类型检查:

declare(strict_types=1);
function strictAdd(int $a, int $b): int {
    return $a + $b;
}
strictAdd("2", 3); // 报错:期望 int,传递了字符串

5. 参数解构(PHP 7.1+)

从数组或对象中解构参数:

function printCoordinates([$x, $y]) {
    echo "X: $x, Y: $y";
}
$point = [3, 5];
printCoordinates($point); // 输出:X: 3, Y: 5

6. 最佳实践

  1. 避免滥用引用传递
    仅在需要函数内部修改外部变量时使用引用,否则优先按值传递。

  2. 合理设置默认值
    默认参数应提供合理的后备值,避免 null 陷阱:

    // 错误:默认值 null 可能导致逻辑漏洞
    function logMessage($message = null) {
        if ($message === null) $message = "No message";
        // ...
    }
    
  3. 优先使用类型声明
    PHP 7+ 的类型约束能显著减少类型错误:

    function safeDivide(int $a, int $b): float {
        if ($b === 0) throw new InvalidArgumentException("除数不能为0");
        return $a / $b;
    }
    
  4. 命名参数提升可读性
    PHP 8+ 的命名参数使代码更清晰:

    setUser(name: "Alice", age: 25); // 明确参数含义
    

总结

特性 说明 适用场景
按值传递 默认方式,安全无副作用 大多数场景
按引用传递 需显式声明 &,直接修改外部变量 需要函数内部修改外部数据时
默认参数 必须放在参数列表末尾 可选参数的函数
可变参数 使用 ...func_get_args() 处理不确定数量的输入
类型声明 强制参数和返回值类型(PHP 7+) 提升代码健壮性
命名参数 明确参数含义(PHP 8+) 跳过可选参数或增强可读性

四,函数体结构

PHP 函数通过 function 关键字定义,其核心由 函数体返回值 组成。合理的函数体设计与返回值处理是编写可维护、高效代码的关键。


一、函数体

函数体是位于 {} 内的代码块,包含函数的核心逻辑。其结构特点如下:

1. 基本语法
function 函数名(参数列表): 返回类型声明 {
    // 函数体逻辑
    return 返回值; // 可选
}
2. 变量作用域
  • 局部变量:函数内定义的变量仅在函数体内有效。

    function calculate() {
        $localVar = 10; // 局部变量
        echo $localVar; // 有效
    }
    calculate();
    echo $localVar; // 报错:未定义变量
    
  • 全局变量:需通过 global$GLOBALS 访问。

    $globalVar = 5;
    function showGlobal() {
        global $globalVar;
        echo $globalVar; // 输出 5
    }
    
3. 函数执行流程
  • 顺序执行:代码从上到下执行,直到遇到 return 或函数结束。
  • return 的作用
    • 终止函数执行,立即返回结果。
    • 未显式 return 时,函数默认返回 null

二、返回值处理
1. 基本返回
  • 单值返回:使用 return 返回单个值。

    function add($a, $b) {
        return $a + $b;
    }
    echo add(3, 5); // 输出 8
    
  • 无返回值:函数默认返回 null

    function logMessage($msg) {
        echo "日志:$msg";
    }
    $result = logMessage("test"); // $result 为 null
    
2. 返回类型声明(PHP 7+)
  • 强制指定返回类型:避免类型不一致问题。

    function divide(int $a, int $b): float {
        return $a / $b;
    }
    echo divide(10, 3); // 输出 3.333...
    
  • 严格模式:使用 declare(strict_types=1); 禁用自动类型转换。

    declare(strict_types=1);
    function strictDivide(int $a, int $b): float {
        return $a / $b;
    }
    strictDivide("10", 3); // 报错:参数类型不匹配
    
3. 多返回值模拟

PHP 不支持直接返回多个值,但可通过以下方式实现:

  • 返回数组

    function getUserInfo() {
        return ['name' => 'Alice', 'age' => 25];
    }
    $user = getUserInfo();
    echo $user['name']; // Alice
    
  • 返回对象

    class User {
        public $name;
        public $age;
    }
    function createUser() {
        $user = new User();
        $user->name = 'Bob';
        $user->age = 30;
        return $user;
    }
    echo createUser()->name; // Bob
    
  • 引用返回(不推荐)

    function &getReference() {
        static $value = 0;
        $value