PHP · Course navigation

PHP closures, array functions, and generators

Transform arrays with map, filter, and reduce, capture variables in closures, and produce values lazily with yield.

On this page
Before you start

PHP functions and arrays.

  • Transform arrays with map, filter, and reduce, capture variables in closures, and produce values lazily with yield.
  • Predict the sample output and explain the state changes.
  • Complete the practice task and check the boundary cases.

The concept

PHP has first-class functions. An arrow function, fn($x) => $x * 2, is a short closure that captures variables from the surrounding scope automatically by value. A full closure, function () use ($rate) { ... }, lists the variables it captures, and use (&$total) captures by reference so the closure can change the outer variable. array_map, array_filter, and array_reduce apply a function across an array.

A generator is a function that uses yield to produce values one at a time. It does not build a whole array in memory, so it can describe very long or even infinite sequences. foreach pulls the next value on each pass. A generator that is only partly consumed does no extra work, which makes it ideal for large files and streams.

Code example

PHP
<?php
$numbers = [1, 2, 3, 4, 5, 6];

$squares = array_map(fn($n) => $n * $n, $numbers);
$evens = array_filter($squares, fn($n) => $n % 2 === 0);
$sum = array_reduce($evens, fn($carry, $n) => $carry + $n, 0);
echo implode(",", $squares), " | ", implode(",", $evens), " | ", $sum, "\n";

$rate = 3;
$multiply = function (int $n) use ($rate) {
    return $n * $rate;
};
echo $multiply(5), "\n";

$total = 0;
array_walk($numbers, function ($n) use (&$total) {
    $total += $n;
});
echo $total, "\n";

function fibonacci(): Generator
{
    [$a, $b] = [0, 1];
    while (true) {
        yield $a;
        [$a, $b] = [$b, $a + $b];
    }
}

$first = [];
foreach (fibonacci() as $value) {
    if (count($first) === 10) {
        break;
    }
    $first[] = $value;
}
echo implode(" ", $first), "\n";
Output
1,4,9,16,25,36 | 4,16,36 | 56
15
21
0 1 1 2 3 5 8 13 21 34

Follow the code

Open the walkthrough to inspect the example one step at a time.

Show guided walkthrough
Guided walkthroughReady
1<?php
2$numbers = [1, 2, 3, 4, 5, 6];
3
4$squares = array_map(fn($n) => $n * $n, $numbers);
5$evens = array_filter($squares, fn($n) => $n % 2 === 0);
6$sum = array_reduce($evens, fn($carry, $n) => $carry + $n, 0);
7echo implode(",", $squares), " | ", implode(",", $evens), " | ", $sum, "\n";
8
9$rate = 3;
10$multiply = function (int $n) use ($rate) {
11 return $n * $rate;
12};
13echo $multiply(5), "\n";
14
15$total = 0;
16array_walk($numbers, function ($n) use (&$total) {
17 $total += $n;
18});
19echo $total, "\n";
20
21function fibonacci(): Generator
22{
23 [$a, $b] = [0, 1];
24 while (true) {
25 yield $a;
26 [$a, $b] = [$b, $a + $b];
27 }
28}
29
30$first = [];
31foreach (fibonacci() as $value) {
32 if (count($first) === 10) {
33 break;
34 }
35 $first[] = $value;
36}
37echo implode(" ", $first), "\n";

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
An arrow function squares every element.—
—
Keep only the even squares. array_filter keeps the original keys.—
—
Fold the remaining values into one number: 4 + 16 + 36.—
—
The three results of the pipeline.—
1,4,9,16,25,36 | 4,16,36 | 56
The closure remembered $rate = 3.—
1,4,9,16,25,36 | 4,16,36 | 56
15
use (&$total) captures by reference, so each call updates the outer variable.—
1,4,9,16,25,36 | 4,16,36 | 56
15
1 + 2 + ... + 6.—
1,4,9,16,25,36 | 4,16,36 | 56
15
21
Pause here and hand the next Fibonacci number to the foreach loop.—
1,4,9,16,25,36 | 4,16,36 | 56
15
21
The generator is infinite, but only ten values were requested before the loop stopped.—
1,4,9,16,25,36 | 4,16,36 | 56
15
21
0 1 1 2 3 5 8 13 21 34

Behind the scenes

How PHP processes this code

The PHP runtime executes the script. echo writes to the response or terminal output.

Cost and common mistakes

array_map, array_filter, and array_reduce are O(n). Each generator step is O(1).

  • A plain function with use ($x) captures by value, so later changes to $x outside are not seen. Use & to share.
  • An infinite generator needs a break or a limit on the consumer side, or the loop never ends.
  • array_filter preserves keys, so the result of the example has keys 1, 3, 5. Use array_values to renumber them.

Try it yourself

How would you take the first 5 even squares lazily?

Reveal answer and reasoning

Write a generator that yields squares one at a time, filter inside the loop, and break after collecting 5 values.

Further reading