Skip to content

闭包(Closure)与匿名函数

闭包是 PHP 中强大的特性,常用于回调、事件处理和延迟执行。

基础用法

php
// 匿名函数赋值给变量
$sayHello = function($name) {
    return "Hello, $name!";
};

echo $sayHello('张三');  // Hello, 张三!

// 作为回调函数
$numbers = [1, 2, 3, 4, 5];
$squared = array_map(function($n) {
    return $n * $n;
}, $numbers);

使用外部变量(use)

php
$taxRate = 0.13;

// 使用外部变量
$calcTax = function($amount) use ($taxRate) {
    return $amount * $taxRate;
};

echo $calcTax(100);  // 13

// 注意:默认是值传递
$multiplier = 2;
$multiply = function($n) use ($multiplier) {
    return $n * $multiplier;
};
$multiplier = 3;
echo $multiply(5);  // 10,不是 15

// 使用引用传递
$count = 0;
$increment = function() use (&$count) {
    $count++;
};
$increment();
$increment();
echo $count;  // 2

绑定 $this(面向对象中使用)

php
class Counter {
    private $count = 0;

    public function getIncrementer() {
        return function() {
            return ++$this->count;
        };
    }
}

$counter = new Counter();
$inc = $counter->getIncrementer();
echo $inc();  // 1
echo $inc();  // 2

静态匿名函数

php
// 静态闭包不绑定 $this
class MyClass {
    public static function getStaticCallback() {
        return static function() {
            // $this 不可用
            return 'static callback';
        };
    }
}

箭头函数(PHP 7.4+)

php
$multiplier = 5;

// 自动捕获外部变量
$multiply = fn($n) => $n * $multiplier;

echo $multiply(10);  // 50

// 多行箭头函数(PHP 8.0+)
$calc = fn($a, $b) => [
    'sum' => $a + $b,
    'diff' => $a - $b
];

延迟执行(惰性求值)

php
class LazyValue {
    private $callback;
    private $value;
    private $resolved = false;

    public function __construct(callable $callback) {
        $this->callback = $callback;
    }

    public function get() {
        if (!$this->resolved) {
            $this->value = ($this->callback)();
            $this->resolved = true;
        }
        return $this->value;
    }
}

// 使用
$expensive = new LazyValue(function() {
    echo "计算中...\n";
    return complexCalculation();
});

// 只有调用 get() 时才执行
$result = $expensive->get();

注意事项

  1. 闭包会保持对外部变量的引用,可能导致内存泄漏
  2. 序列化闭包需要特殊处理(如 opis/closure 库)
  3. 箭头函数不能包含多条语句

Binstork