本章目标

  • 掌握函数的定义和调用
  • 理解参数传递机制
  • 学会使用返回值
  • 了解变量作用域
  • 掌握匿名函数和闭包
  • 学会使用内置函数
  • 理解函数的高级特性

4.1 函数基础

4.1.1 函数定义

基本语法

<?php
// 基本函数定义
function greet() {
    echo "Hello, World!";
}

// 调用函数
greet(); // 输出:Hello, World!

// 带参数的函数
function greetUser($name) {
    echo "Hello, $name!";
}

greetUser("张三"); // 输出:Hello, 张三!

// 带返回值的函数
function add($a, $b) {
    return $a + $b;
}

$result = add(5, 3);
echo $result; // 输出:8

// 带默认参数的函数
function greetWithTitle($name, $title = "先生") {
    return "您好,{$title}{$name}!";
}

echo greetWithTitle("张三");           // 输出:您好,先生张三!
echo greetWithTitle("李四", "女士");   // 输出:您好,女士李四!
?>

4.1.2 函数命名规则

<?php
// 正确的函数名
function calculateTotal() {}
function get_user_info() {}
function isValidEmail() {}
function _privateFunction() {}
function myFunction123() {}

// 错误的函数名
// function 123function() {}    // 不能以数字开头
// function my-function() {}    // 不能包含连字符
// function my function() {}    // 不能包含空格
// function class() {}          // 不能使用关键字

// 函数名不区分大小写
function MyFunction() {
    echo "大写函数";
}

myfunction();  // 可以调用
MYFUNCTION();  // 也可以调用
MyFunction();  // 还是可以调用
?>

4.1.3 函数文档注释

<?php
/**
 * 计算两个数的和
 *
 * 这个函数接受两个数值参数,返回它们的和
 *
 * @param float $a 第一个数
 * @param float $b 第二个数
 * @return float 两数之和
 * @throws InvalidArgumentException 当参数不是数值时
 * @example
 * $result = add(5, 3); // 返回 8
 * $result = add(2.5, 1.5); // 返回 4.0
 */
function add($a, $b) {
    if (!is_numeric($a) || !is_numeric($b)) {
        throw new InvalidArgumentException('参数必须是数值');
    }
    
    return $a + $b;
}

/**
 * 格式化用户信息
 *
 * @param array $user 用户信息数组
 * @param string $format 格式化模板
 * @return string 格式化后的字符串
 * @since 1.0.0
 * @author 张三 <zhangsan@example.com>
 */
function formatUserInfo(array $user, string $format = '{name} ({email})') {
    return str_replace(
        ['{name}', '{email}', '{age}'],
        [$user['name'] ?? '', $user['email'] ?? '', $user['age'] ?? ''],
        $format
    );
}
?>

4.2 参数传递

4.2.1 值传递

<?php
// 值传递(默认方式)
function increment($value) {
    $value++;
    echo "函数内部:$value\n";
}

$number = 5;
increment($number);
echo "函数外部:$number\n";

// 输出:
// 函数内部:6
// 函数外部:5

// 数组的值传递
function modifyArray($arr) {
    $arr[] = 'new item';
    print_r($arr);
}

$myArray = ['item1', 'item2'];
modifyArray($myArray);
print_r($myArray);

// 函数内输出:['item1', 'item2', 'new item']
// 函数外输出:['item1', 'item2']
?>

4.2.2 引用传递

<?php
// 引用传递
function incrementByReference(&$value) {
    $value++;
    echo "函数内部:$value\n";
}

$number = 5;
incrementByReference($number);
echo "函数外部:$number\n";

// 输出:
// 函数内部:6
// 函数外部:6

// 数组的引用传递
function modifyArrayByReference(&$arr) {
    $arr[] = 'new item';
    print_r($arr);
}

$myArray = ['item1', 'item2'];
modifyArrayByReference($myArray);
print_r($myArray);

// 函数内输出:['item1', 'item2', 'new item']
// 函数外输出:['item1', 'item2', 'new item']

// 交换两个变量的值
function swap(&$a, &$b) {
    $temp = $a;
    $a = $b;
    $b = $temp;
}

$x = 10;
$y = 20;
echo "交换前:x=$x, y=$y\n";
swap($x, $y);
echo "交换后:x=$x, y=$y\n";
?>

4.2.3 默认参数

<?php
// 基本默认参数
function createUser($name, $email, $role = 'user', $active = true) {
    return [
        'name' => $name,
        'email' => $email,
        'role' => $role,
        'active' => $active
    ];
}

$user1 = createUser('张三', 'zhangsan@example.com');
$user2 = createUser('李四', 'lisi@example.com', 'admin');
$user3 = createUser('王五', 'wangwu@example.com', 'user', false);

// 默认参数必须在必需参数之后
// function invalidFunction($name = 'default', $email) {} // 错误!

// 使用数组作为默认参数
function processData($data, $options = []) {
    $defaultOptions = [
        'validate' => true,
        'format' => 'json',
        'encoding' => 'utf-8'
    ];
    
    $options = array_merge($defaultOptions, $options);
    
    // 处理数据
    return $options;
}

$result1 = processData($data);
$result2 = processData($data, ['format' => 'xml']);

// 使用null作为默认值
function connectDatabase($host = null, $port = null) {
    $host = $host ?? 'localhost';
    $port = $port ?? 3306;
    
    echo "连接到 $host:$port\n";
}

connectDatabase();
connectDatabase('192.168.1.100');
connectDatabase('192.168.1.100', 3307);
?>

4.2.4 可变参数

<?php
// 使用func_get_args()获取所有参数
function sum() {
    $args = func_get_args();
    $total = 0;
    
    foreach ($args as $arg) {
        if (is_numeric($arg)) {
            $total += $arg;
        }
    }
    
    return $total;
}

echo sum(1, 2, 3, 4, 5);        // 输出:15
echo sum(10, 20);               // 输出:30
echo sum(1.5, 2.5, 3.5);        // 输出:7.5

// 使用func_num_args()获取参数数量
function debugArgs() {
    $numArgs = func_num_args();
    echo "参数数量:$numArgs\n";
    
    for ($i = 0; $i < $numArgs; $i++) {
        $arg = func_get_arg($i);
        echo "参数 $i: $arg\n";
    }
}

debugArgs('a', 'b', 'c');

// PHP 5.6+ 使用...操作符
function sumVariadic(...$numbers) {
    $total = 0;
    foreach ($numbers as $number) {
        $total += $number;
    }
    return $total;
}

echo sumVariadic(1, 2, 3, 4, 5); // 输出:15

// 混合使用固定参数和可变参数
function formatMessage($template, ...$args) {
    return sprintf($template, ...$args);
}

echo formatMessage("Hello %s, you are %d years old", "张三", 25);

// 类型声明的可变参数
function sumIntegers(int ...$numbers): int {
    return array_sum($numbers);
}

echo sumIntegers(1, 2, 3, 4, 5); // 输出:15
?>

4.2.5 命名参数(PHP 8+)

<?php
// PHP 8+ 命名参数
function createUser($name, $email, $role = 'user', $active = true) {
    return [
        'name' => $name,
        'email' => $email,
        'role' => $role,
        'active' => $active
    ];
}

// 使用命名参数
$user1 = createUser(
    name: '张三',
    email: 'zhangsan@example.com'
);

$user2 = createUser(
    email: 'lisi@example.com',
    name: '李四',
    active: false
);

// 混合使用位置参数和命名参数
$user3 = createUser('王五', 'wangwu@example.com', active: false);

// 在数组函数中使用命名参数
$data = ['c' => 3, 'a' => 1, 'b' => 2];
ksort(array: $data, flags: SORT_STRING);

// 在内置函数中使用命名参数
$html = htmlspecialchars(
    string: '<script>alert("XSS")</script>',
    flags: ENT_QUOTES,
    encoding: 'UTF-8'
);
?>

4.3 返回值

4.3.1 基本返回值

<?php
// 返回不同类型的值
function getString() {
    return "Hello World";
}

function getNumber() {
    return 42;
}

function getArray() {
    return [1, 2, 3, 4, 5];
}

function getAssociativeArray() {
    return [
        'name' => '张三',
        'age' => 25,
        'email' => 'zhangsan@example.com'
    ];
}

function getBoolean() {
    return true;
}

// 条件返回
function divide($a, $b) {
    if ($b == 0) {
        return false; // 返回false表示错误
    }
    return $a / $b;
}

$result = divide(10, 2);
if ($result !== false) {
    echo "结果:$result";
} else {
    echo "除数不能为零";
}

// 提前返回
function processUser($user) {
    if (empty($user)) {
        return null;
    }
    
    if (!isset($user['email'])) {
        return false;
    }
    
    // 处理用户逻辑
    return $user;
}
?>

4.3.2 多值返回

<?php
// 使用数组返回多个值
function getNameAndAge() {
    return ['张三', 25];
}

// 使用list()解构
list($name, $age) = getNameAndAge();
echo "姓名:$name,年龄:$age\n";

// PHP 7.1+ 使用数组解构
[$name, $age] = getNameAndAge();

// 返回关联数组
function getUserInfo() {
    return [
        'name' => '张三',
        'age' => 25,
        'email' => 'zhangsan@example.com'
    ];
}

// 解构关联数组
['name' => $userName, 'age' => $userAge] = getUserInfo();

// 使用对象返回多个值
class UserInfo {
    public $name;
    public $age;
    public $email;
    
    public function __construct($name, $age, $email) {
        $this->name = $name;
        $this->age = $age;
        $this->email = $email;
    }
}

function createUserInfo() {
    return new UserInfo('张三', 25, 'zhangsan@example.com');
}

$userInfo = createUserInfo();
echo $userInfo->name;

// 使用生成器返回多个值
function getMultipleValues() {
    yield 'first';
    yield 'second';
    yield 'third';
}

foreach (getMultipleValues() as $value) {
    echo $value . "\n";
}
?>

4.3.3 返回类型声明(PHP 7+)

<?php
// 基本返回类型声明
function getString(): string {
    return "Hello World";
}

function getInteger(): int {
    return 42;
}

function getFloat(): float {
    return 3.14;
}

function getBoolean(): bool {
    return true;
}

function getArray(): array {
    return [1, 2, 3];
}

// 可空返回类型(PHP 7.1+)
function findUser($id): ?User {
    if ($id > 0) {
        return new User();
    }
    return null;
}

// 联合类型(PHP 8+)
function getValue(): int|string {
    if (rand(0, 1)) {
        return 42;
    }
    return "Hello";
}

// void返回类型
function logMessage(string $message): void {
    echo $message . "\n";
    // 不能有return语句,或者只能是return;
}

// never返回类型(PHP 8.1+)
function throwException(): never {
    throw new Exception('This function never returns');
}

// 自定义类返回类型
class User {
    public $name;
}

function createUser(): User {
    return new User();
}

// 接口返回类型
interface UserInterface {
    public function getName(): string;
}

function getUser(): UserInterface {
    return new User();
}
?>

4.4 变量作用域

4.4.1 局部作用域

<?php
$globalVar = "全局变量";

function testLocalScope() {
    $localVar = "局部变量";
    echo $localVar; // 可以访问
    
    // echo $globalVar; // 错误:无法访问全局变量
}

testLocalScope();
// echo $localVar; // 错误:无法访问局部变量

// 函数参数也是局部变量
function processData($data) {
    $data = strtoupper($data); // 修改局部副本
    echo $data;
}

$myData = "hello";
processData($myData);
echo $myData; // 仍然是"hello"
?>

4.4.2 全局作用域

<?php
$globalVar = "全局变量";
$anotherGlobal = "另一个全局变量";

function accessGlobal() {
    global $globalVar;
    echo $globalVar; // 可以访问
    
    $globalVar = "修改后的全局变量";
}

accessGlobal();
echo $globalVar; // 输出:修改后的全局变量

// 使用$GLOBALS数组
function accessGlobalArray() {
    echo $GLOBALS['anotherGlobal'];
    $GLOBALS['anotherGlobal'] = "通过GLOBALS修改";
}

accessGlobalArray();
echo $anotherGlobal; // 输出:通过GLOBALS修改

// 在函数中创建全局变量
function createGlobal() {
    global $newGlobal;
    $newGlobal = "新的全局变量";
}

createGlobal();
echo $newGlobal; // 输出:新的全局变量
?>

4.4.3 静态作用域

<?php
// 静态变量
function counter() {
    static $count = 0;
    $count++;
    echo "调用次数:$count\n";
}

counter(); // 调用次数:1
counter(); // 调用次数:2
counter(); // 调用次数:3

// 静态变量的初始化
function fibonacci($n) {
    static $cache = [];
    
    if (isset($cache[$n])) {
        return $cache[$n];
    }
    
    if ($n <= 1) {
        $cache[$n] = $n;
    } else {
        $cache[$n] = fibonacci($n - 1) + fibonacci($n - 2);
    }
    
    return $cache[$n];
}

echo fibonacci(10); // 使用缓存提高性能

// 多个静态变量
function statistics($value = null) {
    static $sum = 0;
    static $count = 0;
    static $values = [];
    
    if ($value !== null) {
        $sum += $value;
        $count++;
        $values[] = $value;
    }
    
    return [
        'sum' => $sum,
        'count' => $count,
        'average' => $count > 0 ? $sum / $count : 0,
        'values' => $values
    ];
}

statistics(10);
statistics(20);
statistics(30);
print_r(statistics()); // 获取统计信息
?>

4.4.4 超全局变量

<?php
// 超全局变量在任何作用域都可以访问
function showSuperglobals() {
    echo "GET参数:";
    print_r($_GET);
    
    echo "POST参数:";
    print_r($_POST);
    
    echo "SESSION数据:";
    print_r($_SESSION);
    
    echo "COOKIE数据:";
    print_r($_COOKIE);
    
    echo "服务器信息:";
    echo $_SERVER['HTTP_HOST'] . "\n";
    echo $_SERVER['REQUEST_URI'] . "\n";
    
    echo "环境变量:";
    echo $_ENV['PATH'] ?? '未设置';
    
    echo "文件上传:";
    print_r($_FILES);
    
    echo "请求数据:";
    print_r($_REQUEST); // 包含GET、POST、COOKIE
}

// 自定义超全局变量(不推荐)
$GLOBALS['myGlobal'] = "自定义全局变量";

function accessCustomGlobal() {
    echo $GLOBALS['myGlobal'];
}
?>

4.5 匿名函数和闭包

4.5.1 匿名函数

<?php
// 基本匿名函数
$greet = function($name) {
    return "Hello, $name!";
};

echo $greet("张三"); // 输出:Hello, 张三!

// 将匿名函数作为参数传递
function processArray($array, $callback) {
    $result = [];
    foreach ($array as $item) {
        $result[] = $callback($item);
    }
    return $result;
}

$numbers = [1, 2, 3, 4, 5];

// 使用匿名函数计算平方
$squares = processArray($numbers, function($n) {
    return $n * $n;
});

print_r($squares); // [1, 4, 9, 16, 25]

// 使用匿名函数过滤数组
$evenNumbers = array_filter($numbers, function($n) {
    return $n % 2 === 0;
});

print_r($evenNumbers); // [2, 4]

// 使用匿名函数排序
$users = [
    ['name' => '张三', 'age' => 25],
    ['name' => '李四', 'age' => 30],
    ['name' => '王五', 'age' => 20]
];

usort($users, function($a, $b) {
    return $a['age'] - $b['age'];
});

print_r($users); // 按年龄排序
?>

4.5.2 闭包

<?php
// 使用use关键字创建闭包
$message = "Hello";
$name = "张三";

$greet = function() use ($message, $name) {
    return "$message, $name!";
};

echo $greet(); // 输出:Hello, 张三!

// 通过引用捕获变量
$counter = 0;

$increment = function() use (&$counter) {
    $counter++;
    return $counter;
};

echo $increment(); // 1
echo $increment(); // 2
echo $counter;     // 2

// 创建计数器工厂
function createCounter($start = 0) {
    return function() use (&$start) {
        return ++$start;
    };
}

$counter1 = createCounter(10);
$counter2 = createCounter(100);

echo $counter1(); // 11
echo $counter1(); // 12
echo $counter2(); // 101
echo $counter2(); // 102

// 使用闭包实现私有变量
function createBankAccount($initialBalance) {
    $balance = $initialBalance;
    
    return [
        'deposit' => function($amount) use (&$balance) {
            if ($amount > 0) {
                $balance += $amount;
                return $balance;
            }
            return false;
        },
        'withdraw' => function($amount) use (&$balance) {
            if ($amount > 0 && $amount <= $balance) {
                $balance -= $amount;
                return $balance;
            }
            return false;
        },
        'getBalance' => function() use (&$balance) {
            return $balance;
        }
    ];
}

$account = createBankAccount(1000);
echo $account['deposit'](500);    // 1500
echo $account['withdraw'](200);   // 1300
echo $account['getBalance']();    // 1300
?>

4.5.3 箭头函数(PHP 7.4+)

<?php
// 箭头函数语法
$numbers = [1, 2, 3, 4, 5];

// 传统匿名函数
$squares1 = array_map(function($n) {
    return $n * $n;
}, $numbers);

// 箭头函数
$squares2 = array_map(fn($n) => $n * $n, $numbers);

// 箭头函数自动捕获外部变量
$multiplier = 3;
$results = array_map(fn($n) => $n * $multiplier, $numbers);

// 复杂的箭头函数
$users = [
    ['name' => '张三', 'age' => 25],
    ['name' => '李四', 'age' => 30],
    ['name' => '王五', 'age' => 20]
];

$names = array_map(fn($user) => $user['name'], $users);
$adults = array_filter($users, fn($user) => $user['age'] >= 18);

// 嵌套箭头函数
$matrix = [[1, 2], [3, 4], [5, 6]];
$flattened = array_map(fn($row) => array_map(fn($n) => $n * 2, $row), $matrix);

// 条件箭头函数
$grades = [85, 92, 78, 96, 88];
$levels = array_map(
    fn($grade) => $grade >= 90 ? 'A' : ($grade >= 80 ? 'B' : 'C'),
    $grades
);
?>

4.6 内置函数

4.6.1 字符串函数

<?php
$text = "Hello World";

// 字符串长度
echo strlen($text);           // 11
echo mb_strlen("你好世界");    // 4

// 字符串转换
echo strtoupper($text);       // HELLO WORLD
echo strtolower($text);       // hello world
echo ucfirst($text);          // Hello world
echo ucwords($text);          // Hello World

// 字符串查找
echo strpos($text, "World");  // 6
echo strstr($text, "World");  // World
echo substr($text, 6);        // World
echo substr($text, 0, 5);     // Hello

// 字符串替换
echo str_replace("World", "PHP", $text);  // Hello PHP
echo str_ireplace("world", "PHP", $text); // Hello PHP (忽略大小写)

// 字符串分割和连接
$parts = explode(" ", $text);  // ["Hello", "World"]
$joined = implode("-", $parts); // "Hello-World"

// 字符串修剪
$padded = "  Hello World  ";
echo trim($padded);           // "Hello World"
echo ltrim($padded);          // "Hello World  "
echo rtrim($padded);          // "  Hello World"

// 字符串格式化
printf("姓名:%s,年龄:%d\n", "张三", 25);
$formatted = sprintf("价格:%.2f元", 19.99);

// 字符串验证
var_dump(is_string($text));           // true
var_dump(ctype_alpha("abc"));         // true
var_dump(ctype_digit("123"));         // true
var_dump(filter_var("test@example.com", FILTER_VALIDATE_EMAIL));
?>

4.6.2 数组函数

<?php
$numbers = [1, 2, 3, 4, 5];
$fruits = ['apple', 'banana', 'orange'];

// 数组信息
echo count($numbers);         // 5
echo sizeof($numbers);        // 5 (count的别名)
var_dump(empty($numbers));    // false
var_dump(is_array($numbers)); // true

// 数组操作
array_push($fruits, 'grape');     // 添加到末尾
array_unshift($fruits, 'mango');  // 添加到开头
$last = array_pop($fruits);       // 移除并返回最后一个
$first = array_shift($fruits);    // 移除并返回第一个

// 数组搜索
echo array_search('banana', $fruits);  // 返回键名
var_dump(in_array('apple', $fruits));  // true
var_dump(array_key_exists('name', ['name' => '张三'])); // true

// 数组过滤和映射
$evenNumbers = array_filter($numbers, function($n) {
    return $n % 2 === 0;
});

$squares = array_map(function($n) {
    return $n * $n;
}, $numbers);

// 数组归约
$sum = array_reduce($numbers, function($carry, $item) {
    return $carry + $item;
}, 0);

// 数组排序
sort($numbers);           // 升序排序
rsort($numbers);          // 降序排序
asort($fruits);           // 保持键名的升序排序
ksort($fruits);           // 按键名排序

// 数组合并和分割
$merged = array_merge($numbers, $fruits);
$chunks = array_chunk($numbers, 2);  // 分割成每组2个元素
$sliced = array_slice($numbers, 1, 3); // 从索引1开始取3个元素

// 数组键值操作
$keys = array_keys($fruits);
$values = array_values($fruits);
$flipped = array_flip($fruits);  // 键值互换
$combined = array_combine(['a', 'b', 'c'], [1, 2, 3]);
?>

4.6.3 数学函数

<?php
// 基本数学函数
echo abs(-5);           // 5
echo ceil(4.3);         // 5
echo floor(4.7);        // 4
echo round(4.6);        // 5
echo round(4.567, 2);   // 4.57

// 最大值和最小值
echo max(1, 3, 2);      // 3
echo min(1, 3, 2);      // 1
echo max([1, 3, 2]);    // 3

// 幂运算
echo pow(2, 3);         // 8
echo sqrt(16);          // 4
echo exp(1);            // e
echo log(10);           // 自然对数
echo log10(100);        // 2

// 三角函数
echo sin(M_PI / 2);     // 1
echo cos(0);            // 1
echo tan(M_PI / 4);     // 1

// 随机数
echo rand();            // 随机整数
echo rand(1, 10);       // 1-10之间的随机整数
echo mt_rand();         // 更好的随机数生成器
echo random_int(1, 100); // 加密安全的随机整数

// 数字格式化
echo number_format(1234567.89);        // 1,234,568
echo number_format(1234567.89, 2);     // 1,234,567.89
echo number_format(1234567.89, 2, '.', ','); // 1,234,567.89

// 进制转换
echo base_convert('ff', 16, 10);  // 255
echo dechex(255);                 // ff
echo hexdec('ff');                // 255
echo decbin(8);                   // 1000
echo bindec('1000');              // 8
?>

4.6.4 日期时间函数

<?php
// 当前时间
echo time();                    // Unix时间戳
echo date('Y-m-d H:i:s');       // 2024-01-01 12:00:00
echo date('Y-m-d H:i:s', time()); // 指定时间戳

// 日期格式化
echo date('Y年m月d日');          // 2024年01月01日
echo date('l, F j, Y');         // Monday, January 1, 2024
echo date('c');                 // ISO 8601格式
echo date('r');                 // RFC 2822格式

// 时间解析
$timestamp = strtotime('2024-01-01 12:00:00');
$timestamp = strtotime('+1 day');
$timestamp = strtotime('next Monday');
$timestamp = strtotime('last Friday');

// 日期计算
echo date('Y-m-d', strtotime('+1 week'));
echo date('Y-m-d', strtotime('-1 month'));
echo date('Y-m-d', strtotime('+1 year'));

// 日期信息
$info = getdate();
echo $info['year'];    // 年
echo $info['mon'];     // 月
echo $info['mday'];    // 日
echo $info['hours'];   // 小时
echo $info['minutes']; // 分钟
echo $info['seconds']; // 秒

// 检查日期有效性
var_dump(checkdate(2, 29, 2024)); // true (闰年)
var_dump(checkdate(2, 29, 2023)); // false (非闰年)

// 时区设置
date_default_timezone_set('Asia/Shanghai');
echo date_default_timezone_get();

// DateTime类(面向对象方式)
$date = new DateTime();
echo $date->format('Y-m-d H:i:s');

$date->add(new DateInterval('P1D')); // 加1天
echo $date->format('Y-m-d H:i:s');

$date->sub(new DateInterval('PT1H')); // 减1小时
echo $date->format('Y-m-d H:i:s');
?>

4.7 递归函数

4.7.1 基本递归

<?php
// 计算阶乘
function factorial($n) {
    // 基础情况
    if ($n <= 1) {
        return 1;
    }
    
    // 递归情况
    return $n * factorial($n - 1);
}

echo factorial(5); // 120

// 斐波那契数列
function fibonacci($n) {
    if ($n <= 1) {
        return $n;
    }
    
    return fibonacci($n - 1) + fibonacci($n - 2);
}

echo fibonacci(10); // 55

// 优化的斐波那契(使用记忆化)
function fibonacciMemo($n, &$memo = []) {
    if (isset($memo[$n])) {
        return $memo[$n];
    }
    
    if ($n <= 1) {
        $memo[$n] = $n;
    } else {
        $memo[$n] = fibonacciMemo($n - 1, $memo) + fibonacciMemo($n - 2, $memo);
    }
    
    return $memo[$n];
}

echo fibonacciMemo(50); // 快速计算大数

// 计算最大公约数
function gcd($a, $b) {
    if ($b == 0) {
        return $a;
    }
    
    return gcd($b, $a % $b);
}

echo gcd(48, 18); // 6
?>

4.7.2 树形结构递归

<?php
// 目录遍历
function listDirectory($dir, $level = 0) {
    $indent = str_repeat('  ', $level);
    
    if (is_dir($dir)) {
        echo $indent . basename($dir) . "/\n";
        
        $files = scandir($dir);
        foreach ($files as $file) {
            if ($file != '.' && $file != '..') {
                listDirectory($dir . '/' . $file, $level + 1);
            }
        }
    } else {
        echo $indent . basename($dir) . "\n";
    }
}

listDirectory('/path/to/directory');

// 计算目录大小
function getDirectorySize($dir) {
    $size = 0;
    
    if (is_dir($dir)) {
        $files = scandir($dir);
        foreach ($files as $file) {
            if ($file != '.' && $file != '..') {
                $path = $dir . '/' . $file;
                if (is_dir($path)) {
                    $size += getDirectorySize($path);
                } else {
                    $size += filesize($path);
                }
            }
        }
    }
    
    return $size;
}

// 数组递归处理
function arraySum($array) {
    $sum = 0;
    
    foreach ($array as $value) {
        if (is_array($value)) {
            $sum += arraySum($value); // 递归处理子数组
        } else {
            $sum += $value;
        }
    }
    
    return $sum;
}

$nestedArray = [1, [2, 3], [4, [5, 6]], 7];
echo arraySum($nestedArray); // 28

// 多维数组扁平化
function flattenArray($array) {
    $result = [];
    
    foreach ($array as $value) {
        if (is_array($value)) {
            $result = array_merge($result, flattenArray($value));
        } else {
            $result[] = $value;
        }
    }
    
    return $result;
}

$nested = [1, [2, 3], [4, [5, 6]], 7];
$flat = flattenArray($nested);
print_r($flat); // [1, 2, 3, 4, 5, 6, 7]
?>

4.7.3 递归优化

<?php
// 尾递归优化(PHP不支持尾递归优化,但可以手动转换为循环)

// 递归版本(可能栈溢出)
function factorialRecursive($n) {
    if ($n <= 1) {
        return 1;
    }
    return $n * factorialRecursive($n - 1);
}

// 尾递归版本
function factorialTailRecursive($n, $accumulator = 1) {
    if ($n <= 1) {
        return $accumulator;
    }
    return factorialTailRecursive($n - 1, $n * $accumulator);
}

// 循环版本(推荐)
function factorialIterative($n) {
    $result = 1;
    for ($i = 2; $i <= $n; $i++) {
        $result *= $i;
    }
    return $result;
}

// 使用栈模拟递归
function factorialStack($n) {
    $stack = [];
    $result = 1;
    
    // 将所有数字压入栈
    for ($i = $n; $i > 1; $i--) {
        array_push($stack, $i);
    }
    
    // 从栈中弹出并计算
    while (!empty($stack)) {
        $result *= array_pop($stack);
    }
    
    return $result;
}

// 递归深度限制
function limitedRecursion($n, $depth = 0, $maxDepth = 1000) {
    if ($depth > $maxDepth) {
        throw new Exception('递归深度超过限制');
    }
    
    if ($n <= 1) {
        return 1;
    }
    
    return $n * limitedRecursion($n - 1, $depth + 1, $maxDepth);
}
?>

4.8 函数式编程

4.8.1 高阶函数

<?php
// 函数作为参数
function applyOperation($a, $b, $operation) {
    return $operation($a, $b);
}

$add = function($x, $y) { return $x + $y; };
$multiply = function($x, $y) { return $x * $y; };

echo applyOperation(5, 3, $add);      // 8
echo applyOperation(5, 3, $multiply); // 15

// 函数作为返回值
function createMultiplier($factor) {
    return function($number) use ($factor) {
        return $number * $factor;
    };
}

$double = createMultiplier(2);
$triple = createMultiplier(3);

echo $double(5);  // 10
echo $triple(5);  // 15

// 函数组合
function compose($f, $g) {
    return function($x) use ($f, $g) {
        return $f($g($x));
    };
}

$addOne = function($x) { return $x + 1; };
$multiplyTwo = function($x) { return $x * 2; };

$addThenMultiply = compose($multiplyTwo, $addOne);
echo $addThenMultiply(5); // (5 + 1) * 2 = 12

// 柯里化
function curry($func) {
    return function($a) use ($func) {
        return function($b) use ($func, $a) {
            return $func($a, $b);
        };
    };
}

$curriedAdd = curry(function($a, $b) { return $a + $b; });
$addFive = $curriedAdd(5);
echo $addFive(3); // 8
?>

4.8.2 数组函数式操作

<?php
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// 链式操作
$result = array_filter(
    array_map(
        function($n) { return $n * 2; },
        $numbers
    ),
    function($n) { return $n > 10; }
);

print_r($result); // [12, 14, 16, 18, 20]

// 自定义链式操作类
class ArrayPipeline {
    private $data;
    
    public function __construct($data) {
        $this->data = $data;
    }
    
    public function map($callback) {
        $this->data = array_map($callback, $this->data);
        return $this;
    }
    
    public function filter($callback) {
        $this->data = array_filter($this->data, $callback);
        return $this;
    }
    
    public function reduce($callback, $initial = null) {
        return array_reduce($this->data, $callback, $initial);
    }
    
    public function toArray() {
        return array_values($this->data);
    }
}

$pipeline = new ArrayPipeline([1, 2, 3, 4, 5]);
$result = $pipeline
    ->map(fn($n) => $n * 2)
    ->filter(fn($n) => $n > 5)
    ->toArray();

print_r($result); // [6, 8, 10]

// 函数式编程工具函数
function pipe(...$functions) {
    return function($value) use ($functions) {
        return array_reduce($functions, function($carry, $func) {
            return $func($carry);
        }, $value);
    };
}

$transform = pipe(
    fn($n) => $n * 2,
    fn($n) => $n + 1,
    fn($n) => $n / 3
);

echo $transform(5); // ((5 * 2) + 1) / 3 = 3.67
?>

4.9 小结

本章详细介绍了PHP函数的各个方面:

  1. 函数基础:定义、调用、命名规则、文档注释
  2. 参数传递:值传递、引用传递、默认参数、可变参数、命名参数
  3. 返回值:基本返回、多值返回、类型声明
  4. 变量作用域:局部、全局、静态、超全局变量
  5. 匿名函数和闭包:匿名函数、闭包、箭头函数
  6. 内置函数:字符串、数组、数学、日期时间函数
  7. 递归函数:基本递归、树形结构、递归优化
  8. 函数式编程:高阶函数、函数组合、链式操作

4.10 实践练习

  1. 基础函数练习

    • 编写各种计算函数(面积、体积等)
    • 实现字符串处理函数
    • 创建数据验证函数
  2. 高级特性练习

    • 使用闭包实现计数器
    • 编写递归函数处理树形数据
    • 实现函数式编程工具
  3. 实际应用练习

    • 创建用户认证系统
    • 实现数据处理管道
    • 编写文件操作工具函数
  4. 性能优化练习

    • 优化递归函数
    • 实现函数缓存机制
    • 比较不同实现方式的性能

4.11 扩展阅读

  1. PHP函数官方文档
  2. PHP内置函数参考
  3. 函数式编程思想
  4. 递归算法设计
  5. PHP性能优化指南

下一章预告:在下一章中,我们将学习PHP的数组,包括索引数组、关联数组、多维数组以及各种数组操作函数。