Question
In PHP 5.3, what does this anonymous function syntax mean, particularly the use ($tax, &$total) clause?
public function getTotal($tax)
{
$total = 0.00;
$callback = function ($quantity, $product) use ($tax, &$total) {
$pricePerItem = constant(
__CLASS__ . '::PRICE_' . strtoupper($product)
);
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
array_walk($this->products, $callback);
return round($total, 2);
}
What is a closure in PHP, why is use needed here, and when is this pattern appropriate to use?
Short Answer
A PHP closure is an anonymous function that can be stored in a variable, passed to another function, and executed later. The use clause explicitly gives the closure access to variables from the surrounding scope. In this example, $tax is copied into the closure and $total is imported by reference so the callback can update it.
Concept
A closure is an anonymous function together with the variables it captures from the scope where it was created.
Anonymous functions are useful as callbacks: small pieces of behavior passed to functions such as array_walk, array_filter, and usort.
PHP functions have their own local scope. Therefore, a variable created outside an anonymous function is not automatically available inside it:
$tax = 0.20;
$calculate = function ($price) {
// $tax is not available here.
return $price * (1 + $tax);
};
The use clause solves this by importing selected variables from the surrounding scope:
$calculate = function ($price) use ($tax) {
return $price * (1 + $tax);
};
In the original code:
Mental Model
Think of an anonymous function as a worker sent to process each item in a list.
The worker has its own workspace, so it cannot automatically see everything on your desk outside the workspace. The use clause is the set of items you put into the worker's bag before sending it out.
use ($tax)puts a photocopy of the tax rate in the bag.use (&$total)gives the worker access to the same shared tally sheet. Each time it processes an item, it can update the original total.
The & means “share this variable,” rather than “make a copy of its current value.”
Syntax and Examples
The general closure syntax is:
$function = function (parameters) use (outerVariables) {
// function body
};
A closure can then be called like a normal function:
$greeting = 'Hello';
$welcome = function ($name) use ($greeting) {
return $greeting . ', ' . $name . '!';
};
echo $welcome('Ava'); // Hello, Ava!
$greeting is defined outside the closure, so it must be listed in use.
Capture by value
Without &, PHP captures the variable's value at the time the closure is created:
$discount = ;
= {
* ( - );
};
= ;
();
Step by Step Execution
Consider this smaller example:
$tax = 0.20;
$total = 0.00;
$items = [
'book' => 2,
'pen' => 3,
];
$prices = [
'book' => 10.00,
'pen' => 2.00,
];
array_walk($items, function ($quantity, $product) use ($tax, &$total, $prices) {
$total += $prices[$product] * $quantity * (1 + $tax);
});
echo $total; // 31.2
Execution proceeds as follows:
$taxis0.20, and$totalstarts at0.00.- PHP creates the closure. It captures
$taxand$pricesby value, and by reference.
Real World Use Cases
Closures with use are common when a callback needs context from its surrounding code.
- Filtering search results: Capture a minimum price or selected category.
- Sorting: Capture a configuration setting that controls sort behavior.
- Validation: Capture allowed values, a current user, or a validation rule.
- Data transformation: Capture exchange rates, tax rates, or formatting options while mapping records.
- Event handlers: Capture an ID or service needed when an event occurs later.
- Retries and error handling: Capture an operation's context for a callback that runs after a failure.
For example, filter products using a user-selected maximum price:
$maxPrice = 50;
$affordableProducts = array_filter(
$products,
function (array $product) use ($maxPrice) {
return $product['price'] <= $maxPrice;
}
);
Real Codebase Usage
In production PHP code, closures are often short, focused callbacks. Capturing configuration by value is especially common:
$allowedRoles = ['admin', 'editor'];
$canAccess = function (string $role) use ($allowedRoles): bool {
return in_array($role, $allowedRoles, true);
};
A common pattern is a guard clause inside a callback, which skips invalid records early:
$activeEmails = array_filter($users, function (array $user): bool {
if (!isset($user['email'])) {
return false;
}
return $user['active'] === true;
});
When transforming data, prefer returning a value from array_map() rather than mutating an outside variable by reference:
Common Mistakes
Forgetting use
Outer local variables are not automatically in a closure's scope.
$rate = 0.20;
$withTax = function ($price) {
return $price * (1 + $rate); // Undefined variable $rate
};
Fix it by importing the variable:
$withTax = function ($price) use ($rate) {
return $price * (1 + $rate);
};
Expecting a by-value capture to change later
$rate = 0.10;
$calculate = function ($price) use ($rate) {
return * ( + );
};
= ;
();
Comparisons
| Feature | What it does | Best use |
|---|---|---|
| Named function | Defines reusable behavior with a name | Logic used in many places |
| Anonymous function | Defines behavior without a name | A one-off callback |
Closure with use | Anonymous function that captures local variables | Callback needs surrounding context |
use ($value) | Captures the current value | Stable configuration such as a tax rate |
use (&$value) | Shares the original variable by reference | Deliberate counters or accumulators |
foreach loop | Iterates with visible local state | Straightforward processing and accumulation |
Cheat Sheet
// Create an anonymous function
$callback = function ($value) {
return $value * 2;
};
// Capture an outer variable by value
$callback = function ($value) use ($multiplier) {
return $value * $multiplier;
};
// Capture an outer variable by reference
$callback = function ($value) use (&$total) {
$total += $value;
};
- A closure is an anonymous function that captures surrounding variables.
useimports local variables from the enclosing scope.use ($name)captures the value when the closure is created.use (&$name)shares the original variable and permits outer-state changes.- Variables must be defined before creating the closure.
- Closure parameters, such as
function ($value), are separate from captured variables in .
FAQ
What is a closure in PHP?
A closure is an anonymous function that can capture variables from the scope where it is created. It can be stored in a variable, passed as a callback, and called later.
Why does PHP use the use keyword with closures?
PHP closures have their own scope. use explicitly imports selected variables from the surrounding local scope into the closure.
What is the difference between use ($variable) and use (&$variable)?
Without &, the closure receives a captured value. With &, it shares the original variable by reference, so changes made inside the closure affect the outside variable.
Is use the same as importing a namespace in PHP?
No. Namespace imports use use at file or namespace scope, such as use App\Service\Mailer;. Closure use appears after a function's parameter list and captures local variables. They are different language features that use the same keyword.
Can a closure access global variables without use?
Not automatically. A closure can use the global keyword, but explicitly capturing required variables with is generally clearer and easier to test.
Mini Project
Description
Build a small invoice calculator that uses a closure to add tax to line items. The project demonstrates capturing a fixed tax rate by value and calculating a total without changing global state.
Goal
Calculate the tax-inclusive total for a list of invoice items using array_reduce() and a closure.
Requirements
Define an array of invoice items containing a name, quantity, and unit price.
Store the tax rate in a variable outside the closure.
Use a closure that captures the tax rate with use.
Calculate and display the final total rounded to two decimal places.
Do not use a global variable.
Keep learning
Related questions
Are PDO Prepared Statements Enough to Prevent SQL Injection in PHP?
Learn how PDO prepared statements prevent SQL injection in PHP, what they protect, and the mistakes that still leave MySQL apps vulnerable.
Can You Bind an Array to an IN Clause in PHP PDO?
Learn how PDO handles placeholders in IN() clauses, why arrays cannot be bound directly, and the safe PHP pattern to build dynamic queries.
Choosing the Right MySQL Collation for PHP and UTF-8
Learn how MySQL character sets and collations work with PHP, and how to choose a practical UTF-8 setup for web applications.