Closure in PHP: A Complete Guide

Updated: January 9, 2024 By: Guest Contributor Post a comment

Introduction

Closures, a concept often associated with functional programming, have become a powerful component in modern PHP development. This guide unpacks the mystery behind closures in PHP, demonstrating how they can be leveraged for cleaner and more modular code.

Understanding Closures

In PHP, a closure is an anonymous function that can capture variables from its surrounding scope. These functions allow you to encapsulate functionality and they have great synergy with callback patterns.

<?php
$value = 10;
$closure = function() use ($value) {
    return $value + 20;
};
echo $closure();  // Outputs: 30
?>

Variable Inheritance

Closures ‘inherit’ variables from the parent scope using the use keyword. This allows the function to maintain state in a controlled manner.

<?php
$incrementBy = 5;
$adder = function($num) use ($incrementBy) {
    return $num + $incrementBy;
};
echo $adder(10);  // Outputs: 15
?>

Changing External Variables

Since PHP 5.4, you can also pass variable by reference to a closure, allowing it to modify external variables.

<?php
$count = 0;
$increment = function() use (&$count) {
    $count++;
};
$increment();
echo $count;  // Outputs: 1
?>

Use in Built-in Functions

Closures are often passed as callbacks to PHP’s array functions like array_filter and array_map.

<?php
$numbers = [1, 2, 3, 4, 5];
$even = array_filter($numbers, function($num) {
    return $num % 2 === 0;
});
print_r($even);  // Outputs: Array ( [1] => 2 [3] => 4 )
?>

Advanced Closure Concepts

Using Callable Type

PHP supports type hinting for callables, allowing you to ensure that a variable is a valid function or closure.

<?php
function runCalculation(callable $operation, $num1, $num2) {
    return $operation($num1, $num2);
}
$result = runCalculation(function($a, $b){ return $a + $b; }, 5, 10);
echo $result;  // Outputs: 15
?>

Closures and Object Scope

Closures can also be bound to an object’s scope, allowing them to access the object’s private and protected properties.

<?php
class Test {
    private $value = 1;
    public function getClosure() {
        return function() { return ++$this->value; };
    }
}
$test = new Test();
$closure = $test->getClosure();
$closure = $closure->bindTo($test, 'Test');
echo $closure();  // Outputs: 2
?>

Static Variables

Closures can maintain state between invocations using static variables.

<?php
$counter = function() {
    static $count = 0;
    $count++;
    return $count;
};
echo $counter();  // Outputs: 1
echo $counter();  // Outputs: 2
?>

Serialization

Since PHP 7.4, closures can be serialized and deserialized, making it easier to pass them around or store them for later use.

<?php
$serializeClosure = function($value) {
    return $value * 2;
};
$serialized = serialize(new SerializableClosure($serializeClosure));
$unserializedClosure = unserialize($serialized);
echo $unserializedClosure(5);  // Outputs: 10
?>

Conclusion

Closures in PHP offer a robust way to create anonymous functions that can capture variables from the surrounding scope and maintain state. By mastering closures, you open the door to a more functional programming style within PHP, with greater modularity and separation of concerns in your codebase.