PHP项目函数式编程特性

wen PHP项目 2

PHP 函数式编程特性

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

PHP项目函数式编程特性

闭包(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"

最佳实践建议

  1. 优先使用纯函数 - 提高可测试性和可预测性
  2. 避免副作用 - 不要修改外部变量
  3. 使用不可变数据 - 创建新数组而不是修改原数组
  4. 合理使用闭包 - 避免过多嵌套导致代码难以维护
  5. 结合OOP使用 - 设计模式混合使用效果更好

PHP 的函数式编程特性虽然不是最完善的,但对于提高代码质量和可维护性非常有用。

抱歉,评论功能暂时关闭!