Skip to Content
Course content

13: Anonymous Functions and Closures

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Up until now, every function we've written has had a name. That's great for things you use everywhere, but sometimes you just need a bit of logic for a one-off task—like filtering a list or sorting a weirdly structured array. In those cases, naming a function feels like overkill. That's where anonymous functions (and their more powerful cousins, closures) come in.

Creating a quick filter on the fly

Let's say we're building a simple product catalog. We have an array of products, and we want to filter them. Instead of writing five different functions for "cheap products," "expensive products," and "out of stock products," I'm going to write one generic filter function that accepts another function as an argument. This is a common pattern in functional programming.

$products = [
    ['name' => 'Mechanical Keyboard', 'price' => 120, 'stock' => 5],
    ['name' => 'Gaming Mouse', 'price' => 60, 'stock' => 0],
    ['name' => 'UltraWide Monitor', 'price' => 450, 'stock' => 2],
    ['name' => 'USB-C Cable', 'price' => 15, 'stock' => 20],
];

function filterProducts(array $products, callable $callback) {
    $filtered = [];
    foreach ($products as $product) {
        if ($callback($product)) {
            $filtered[] = $product;
        }
    }
    return $filtered;
}

// Here's the anonymous function. No name, just logic.
$cheapProducts = filterProducts($products, function($product) {
    return $product['price'] < 100;
});

print_r($cheapProducts);

See what happened there? I passed a function directly into filterProducts. I didn't have to define a global isCheap() function that I'll never use again. It's clean and keeps the logic right where it's being used.

Where I usually trip up: Scope

Now, let's make it more dynamic. I want to let the user decide the price threshold. I'll define a variable $maxPrice and try to use it inside my anonymous function. I'll write this the way I did the first time I learned PHP, which is the wrong way.

$maxPrice = 50;

$budgetProducts = filterProducts($products, function($product) {
    // I'm assuming $maxPrice is available here because it's in the outer scope.
    return $product['price'] < $maxPrice;
});

print_r($budgetProducts);

If you run this, you'll notice it returns an empty array or throws a warning. Why? Because in PHP, anonymous functions don't automatically inherit variables from the parent scope. They are isolated. I just tried to access $maxPrice, but the function has no idea what that is. It's a classic "gotcha" that has cost me plenty of debugging hours over the years.

Closing the gap with the 'use' keyword

To fix this, we turn the anonymous function into a closure. A closure "closes over" the variables it needs from the outside world. In PHP, we do this explicitly using the use keyword in the function signature.

$maxPrice = 50;

// We explicitly tell PHP to bring $maxPrice into the function's scope
$budgetProducts = filterProducts($products, function($product) use ($maxPrice) {
    return $product['price'] < $maxPrice;
});

print_r($budgetProducts);

Now it works. By adding use ($maxPrice), I've effectively captured that variable at the moment the function was created. One thing to keep in mind: the variable is captured by value by default. If you change $maxPrice after the closure is defined, the closure will still use the value it had when it was first created. If you need it to stay synced, you'd pass it by reference using use (&$maxPrice), but you'll rarely need to do that for simple filtering.




📋 Practical Task

Building a Dynamic Tax Calculator

You are building a checkout system where different states have different tax rates. Instead of writing a separate function for every state, you will use a closure to create a flexible tax applicator.

Your Task:

  • Create an array of order totals (e.g., [100, 250, 40, 10]).
  • Define a variable $taxRate (e.g., 0.07 for 7%).
  • Write a function called applyTax that takes an array of amounts and a callable. The applyTax function should return a new array where the callback has been applied to every amount.
  • Call applyTax using an anonymous function that uses the use keyword to bring in the $taxRate and calculate the total (Amount + (Amount * TaxRate)).
  • Print the resulting array of taxed totals to the screen.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.