function (...) { ... } without a name yields a Closure object you can store, pass and return. Unlike JavaScript, a PHP closure sees no outer variables unless you list them in use: use ($rate) copies the value when the closure is created, and use (&$sold) binds the variable itself. A closure created in a method captures $this, and Closure::call() runs one with any object as $this, private members included.
<?php
declare(strict_types=1);
$rate = 0.06;
$withTax = function (float $p) use ($rate): float { return $p * (1 + $rate); };
$rate = 0.10; // too late: $rate was copied
$sold = 0;
$sell = function (int $qty) use (&$sold): void { $sold += $qty; }; // shares $sold
$sell(2);
$sell(3);
final class Cart
{
private array $items = ['PHP Pocket Guide' => 12.5, 'SQL Workbook' => 18.0];
}
$sum = function (): float { return array_sum($this->items); };
echo $withTax(100.0), " sold $sold total ", $sum->call(new Cart()), "\n";Output
106 sold 5 total 30.5
Write static function when a closure needs no $this: a captured $this keeps the whole object alive as long as the closure, a common leak in long-running workers (Asynchronous PHP).