PHP 函数式编程特性
PHP 虽然传统上被视为面向对象编程语言,但从 PHP 5.3 开始引入了许多函数式编程特性,以下是主要的函数式编程特性:

闭包(Closure)
// 基础闭包
$greeting = function($name) {
return "Hello, $name!";
};
echo $greeting("World"); // Hello, World!
// 闭包捕获外部变量
$message = "Welcome";
$greet = function($name) use ($message) {
return "$message, $name!";
};
echo $greet("John"); // Welcome, John!
匿名函数
$numbers = [1, 2, 3, 4, 5];
// 使用匿名函数
$squared = array_map(function($n) {
return $n * $n;
}, $numbers);
print_r($squared); // [1, 4, 9, 16, 25]
高阶函数
// 返回函数的函数
function multiplier($factor) {
return function($number) use ($factor) {
return $number * $factor;
};
}
$double = multiplier(2);
echo $double(5); // 10
$triple = multiplier(3);
echo $triple(5); // 15
数组函数式操作
$numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
// array_map - 映射
$squared = array_map(fn($n) => $n ** 2, $numbers);
// array_filter - 过滤
$even = array_filter($numbers, fn($n) => $n % 2 === 0);
// array_reduce - 归约
$sum = array_reduce($numbers, fn($carry, $n) => $carry + $n, 0);
// array_walk - 遍历
$result = [];
array_walk($numbers, function($value, $key) use (&$result) {
$result[$key] = $value * 2;
});
箭头函数(PHP 7.4+)
// 传统闭包
$double1 = function($x) { return $x * 2; };
// 箭头函数(更简洁)
$double2 = fn($x) => $x * 2;
// 自动捕获外部变量
$factor = 3;
$multiply = fn($x) => $x * $factor; // 无需 use 关键字
// 实际应用示例
$prices = [10, 20, 30, 40];
$discounted = array_map(fn($price) => $price * 0.9, $prices);
不可变性(Immutability)
// 使用不可变集合
$original = ['a', 'b', 'c'];
// 创建新数组而不是修改原数组
$modified = array_map('strtoupper', $original);
// 字符串也是不可变的
$str = "Hello";
$newStr = str_replace("H", "J", $str);
echo $str; // Hello (原字符串不变)
echo $newStr; // Jello (新字符串)
函数组合
function compose(callable ...$functions) {
return function($input) use ($functions) {
return array_reduce(
$functions,
function($carry, $fn) {
return $fn($carry);
},
$input
);
};
}
$addOne = fn($x) => $x + 1;
$multiplyByTwo = fn($x) => $x * 2;
$square = fn($x) => $x ** 2;
$pipeline = compose($addOne, $multiplyByTwo, $square);
echo $pipeline(3); // ((3 + 1) * 2)^2 = 64
纯函数示例
// 纯函数:相同的输入总是产生相同的输出,没有副作用
function pureAdd($a, $b) {
return $a + $b;
}
// 非纯函数:有副作用
$count = 0;
function impureAdd($a) {
global $count;
$count++;
return $a + $count;
}
// 使用纯函数的优势
class Calculator {
private function add($a, $b) {
return $a + $b;
}
public function calculate($x, $y) {
// 使用多个纯函数组合
return $this->add($x, $y) * 2;
}
}
Partial Application(部分应用)
function partial(callable $func, ...$args) {
return function(...$remaining) use ($func, $args) {
return $func(...array_merge($args, $remaining));
};
}
// 示例:创建特定的数学函数
$add = function($a, $b) {
return $a + $b;
};
$addFive = partial($add, 5);
echo $addFive(3); // 8
// 更实际的例子:价格计算
$calculateTotal = function($tax, $discount, $price) {
return $price * (1 + $tax) * (1 - $discount);
};
$calculateWithTax = partial($calculateTotal, 0.1); // 固定税率10%
$finalPrice = $calculateWithTax(0.2, 100); // 20%折扣,原价100
echo $finalPrice; // 88
Currying(柯里化)
function curry(callable $func, ...$args) {
$arity = (new ReflectionFunction($func))->getNumberOfRequiredParameters();
// 如果参数已足够,直接执行
if (count($args) >= $arity) {
return $func(...$args);
}
// 否则返回新函数等待更多参数
return function(...$more) use ($func, $args) {
return curry($func, ...$args, ...$more);
};
}
// 示例
$multiply = function($a, $b, $c) {
return $a * $b * $c;
};
$curried = curry($multiply);
$result = $curried(2)(3)(4); // 24
echo $result; // 24
函数式编程库
// 使用函数式编程库(如 Laravel Collections)
$collection = collect([1, 2, 3, 4, 5, 6]);
$result = $collection
->filter(fn($item) => $item > 2)
->map(fn($item) => $item * 2)
->reduce(fn($carry, $item) => $carry + $item, 0);
echo $result; // (3*2 + 4*2 + 5*2 + 6*2) = 36
实际应用示例:数据处理管道
// 用户数据处理
$users = [
['name' => 'John', 'age' => 25, 'active' => true],
['name' => 'Jane', 'age' => 17, 'active' => true],
['name' => 'Bob', 'age' => 30, 'active' => false],
['name' => 'Alice', 'age' => 22, 'active' => true],
];
// 函数式方式处理
$activeAdults = array_map(
fn($user) => $user['name'],
array_filter(
$users,
fn($user) => $user['active'] && $user['age'] >= 18
)
);
// 或者更直观的管道方式
$pipeline = compose(
fn($users) => array_filter($users, fn($u) => $u['active']),
fn($users) => array_filter($users, fn($u) => $u['age'] >= 18),
fn($users) => array_map(fn($u) => $u['name'], $users),
fn($names) => implode(', ', $names)
);
echo $pipeline($users); // "John, Alice"
最佳实践建议
- 优先使用纯函数 - 提高可测试性和可预测性
- 避免副作用 - 不要修改外部变量
- 使用不可变数据 - 创建新数组而不是修改原数组
- 合理使用闭包 - 避免过多嵌套导致代码难以维护
- 结合OOP使用 - 设计模式混合使用效果更好
PHP 的函数式编程特性虽然不是最完善的,但对于提高代码质量和可维护性非常有用。