Skip to main content

Command Palette

Search for a command to run...

PHP Closures: Comprehensive Guide with Examples

Published
4 min readView as Markdown

A closure in PHP is an anonymous function that can be assigned to a variable and passed around like any other object. Closures allow you to encapsulate functionality in a callable format, making your code more flexible and reusable. PHP closures are powerful tools in functional programming and are often used in frameworks like Laravel.


1. Defining a Closure

A closure is created using the function keyword without specifying a name.

Basic Example:

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

echo $greet('John'); // Outputs: Hello, John!

2. Assigning Closures to Variables

Closures can be stored in variables, making them easy to reuse.

Example:

$add = function ($a, $b) {
    return $a + $b;
};

echo $add(5, 3); // Outputs: 8

3. Passing Closures as Arguments

Closures can be passed as arguments to other functions.

Example:

function process($callback) {
    return $callback('World');
}

echo process(function ($name) {
    return "Hello, $name!";
}); // Outputs: Hello, World!

4. Returning Closures from Functions

Functions can return closures.

Example:

function multiplier($factor) {
    return function ($value) use ($factor) {
        return $value * $factor;
    };
}

$double = multiplier(2);
echo $double(10); // Outputs: 20

$triple = multiplier(3);
echo $triple(10); // Outputs: 30

5. Using Closures with use

Closures can inherit variables from the parent scope using the use keyword.

Example:

$prefix = 'Hello';

$sayHello = function ($name) use ($prefix) {
    return "$prefix, $name!";
};

echo $sayHello('Alice'); // Outputs: Hello, Alice!

6. Binding Closures to Objects

Closures can be bound to objects using the bindTo or Closure::bind.

Example:

class Greeter {
    private $name = 'World';
}

$closure = function () {
    return "Hello, $this->name!";
};

$boundClosure = $closure->bindTo(new Greeter());
echo $boundClosure(); // Outputs: Hello, World!

7. Using Closures in Array Functions

Closures are commonly used with array functions like array_map, array_filter, and array_reduce.

Example with array_map:

$numbers = [1, 2, 3, 4];
$doubled = array_map(function ($n) {
    return $n * 2;
}, $numbers);

print_r($doubled); // Outputs: [2, 4, 6, 8]

Example with array_filter:

$numbers = [1, 2, 3, 4];
$even = array_filter($numbers, function ($n) {
    return $n % 2 === 0;
});

print_r($even); // Outputs: [2, 4]

Example with array_reduce:

$numbers = [1, 2, 3, 4];
$sum = array_reduce($numbers, function ($carry, $item) {
    return $carry + $item;
}, 0);

echo $sum; // Outputs: 10

8. Static Closures

You can define a closure as static, meaning it does not inherit the $this context from an enclosing object.

Example:

$staticClosure = static function ($x, $y) {
    return $x + $y;
};

echo $staticClosure(3, 5); // Outputs: 8

9. Closures in Classes

Closures can be used as methods or stored as properties in classes.

Storing as Properties:

class Math {
    public $add;

    public function __construct() {
        $this->add = function ($a, $b) {
            return $a + $b;
        };
    }
}

$math = new Math();
$add = $math->add;
echo $add(2, 3); // Outputs: 5

Passing Closures to Methods:

class Calculator {
    public function compute($a, $b, callable $operation) {
        return $operation($a, $b);
    }
}

$calc = new Calculator();
echo $calc->compute(4, 2, function ($a, $b) {
    return $a * $b;
}); // Outputs: 8

10. Closures as Middleware

Closures are widely used in middleware for request handling.

$middleware = function ($request, $next) {
    $request['middleware'] = 'processed';
    return $next($request);
};

$handler = function ($request) {
    return $request;
};

$finalRequest = $middleware(['data' => 'test'], $handler);
print_r($finalRequest); // Outputs: ['data' => 'test', 'middleware' => 'processed']

11. Closures in Laravel

Laravel makes extensive use of closures for various tasks:

Routes:

Route::get('/', function () {
    return 'Welcome to Laravel!';
});

Middleware:

Route::middleware(function ($request, $next) {
    // Modify request
    return $next($request);
});

Collections:

$collection = collect([1, 2, 3]);
$doubled = $collection->map(function ($item) {
    return $item * 2;
});
print_r($doubled->all()); // Outputs: [2, 4, 6]

12. Advantages of Closures

  1. Flexibility: Closures provide dynamic behavior by encapsulating logic in a callable format.
  2. Reusability: They reduce repetition by enabling modular, reusable code.
  3. Encapsulation: Closures can capture variables from the parent scope for scoped behavior.

13. Limitations of Closures

  1. Complexity: Overuse of closures can make code harder to read and maintain.
  2. Debugging: Debugging closures can sometimes be tricky, especially in large, nested applications.

Closures are a versatile and essential feature of PHP, enabling developers to write cleaner, modular, and more flexible code.

More from this blog

Khang Nguyen

119 posts