Closures & Arrow Functions
Functions in PHP are values — you can store them in variables, pass them as arguments, and return them from other functions. Master closures and the concise fn() => arrow syntax, and the whole world of array_map , array_filter and callbacks opens up.
Learn Closures & Arrow Functions in our free PHP course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick recall.
Part of the free Php course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
1️⃣ Anonymous Functions as Values
An anonymous function (also called a closure ) is a function with no name. You assign it to a variable and call it through that variable with () . Because it's just a value, you can also pass it into another function — any parameter typed callable will accept it.
2️⃣ Capturing Scope with use()
Here's the part that surprises newcomers: a PHP closure does not automatically see variables from the code around it. You import the ones you need with use(...) . By default use($x) captures a copy of the value at the moment the closure is defined. Add an ampersand — use(&$x) — to capture by reference so the closure and the outer code share one live variable.
3️⃣ Arrow Functions
Arrow functions (PHP 7.4+) are a compact closure for a single expression : fn($x) => $x * 2 . They have two superpowers over the long form: there's an implicit return , and they auto-capture outer variables by value — no use() needed. The trade-off is they're limited to one expression.
4️⃣ The Array-Function Trio
Closures really earn their keep with PHP's higher-order array functions. array_filter keeps items where your closure returns true , array_map transforms each item, and array_reduce folds a list down to a single value. Arrow functions make these read almost like English.
Now you try — fill in each ___ using the 👉 hint, then run it and check against the Output panel.
These lines build a by-reference counter closure — but they're scrambled. Put them in the order that prints 2 .
Initialise $n ( B ), define the closure that captures it by reference ( D ), call it twice ( A , E ) so $n becomes 2, then echo it ( C ). The closure must exist before you call it.
6 — the arrow function captured $x by value (5) when it was defined. Reassigning $x to 100 afterwards has no effect.
1,4,9 — each element is squared by the arrow function.
7 — capturing by reference ( &$total ) lets the closure mutate the outer variable across both calls.
📋 Quick Reference — Closures
No code is filled in this time — just a brief and an outline. Write it yourself, run it on onecompiler.com/php or your own machine, then check your result against the expected output in the comments.
Practice quiz
How does a classic closure (function (...) { ... }) access a variable from the surrounding scope?
- Automatically, like JavaScript
- Only with the global keyword
- You must import it with use()
- It cannot access outer variables
Answer: You must import it with use(). A PHP closure does not inherit outer scope automatically. You explicitly import variables with use($var).
What prints? $x = 5; $f = fn($n) => $n + $x; $x = 100; echo $f(1);
- 6
- 101
- 1
- 105
Answer: 6. The arrow function auto-captured $x by value (5) when defined. Reassigning $x to 100 afterwards has no effect, so 1 + 5 = 6.
What does use(&$x) with the ampersand do?
- Captures a copy of $x
- Makes $x read-only
- Renames $x inside the closure
- Captures $x by reference, sharing the live variable
Answer: Captures $x by reference, sharing the live variable. use(&$x) captures by reference: the closure shares the same variable as the outer scope and can read and modify the live value.
How do arrow functions (fn() =>) capture outer variables?
- They require use()
- They auto-capture by value any variable they reference
- They auto-capture by reference
- They cannot capture anything
Answer: They auto-capture by value any variable they reference. Arrow functions automatically capture by value any outer variable they mention — no use() needed.
What is the body limitation of an arrow function?
- It is limited to a single expression
- It can have at most 3 statements
- It cannot take parameters
- It cannot return a value
Answer: It is limited to a single expression. An arrow function (fn(...) => expression) is limited to one expression, with an implicit return. Use a full closure for multiple statements.
What does echo implode(',', array_map(fn($n) => $n * $n, [1, 2, 3])); print?
- 1,2,3
- 2,4,6
- 1,4,9
- 1,8,27
Answer: 1,4,9. array_map squares each element with the arrow function: 1, 4, 9.
With $tax = 0.2; $f = function ($p) use ($tax) { return $p + $p * $tax; }; then $tax = 0.5; what is $f(100)?
- 150
- 120
- 100
- 105
Answer: 120. use($tax) captured a copy of 0.2 at definition time. Changing $tax to 0.5 afterwards does not affect the closure, so 100 + 20 = 120.
Which array helper folds a list down to a single value?
- array_map
- array_filter
- array_merge
- array_reduce
Answer: array_reduce. array_reduce folds a list into one value (e.g. a running total); array_map transforms and array_filter keeps items.
What does the callable type hint mean?
- Only a closure is accepted
- method
Answer: method. callable means 'something you can call like a function' — a closure, a function name string, an [object, 'method'] array, or an invokable object.
After $total = 0; $add = function ($n) use (&$total) { $total += $n; }; $add(3); $add(4); what is $total?
- 0
- 3
- 7
- 4
Answer: 7. Capturing by reference (&$total) lets the closure mutate the outer variable across both calls: 3 + 4 = 7.