Learn how to replace create_function() with anonymous functions in PHP. This guide covers the benefits, syntax, best practices, and security improvements when transitioning to closures for modern PHP development.
If you’re running PHP 8 and your old code calls create_function(), it doesn’t warn you anymore. It just dies. The function was deprecated in PHP 7.2 and removed outright in PHP 8.0, so any legacy script still reaching for it now throws a fatal error the moment it runs.
The fix is the same one PHP has recommended for years: anonymous functions, also called closures. They do everything create_function() did, without the string parsing, the security holes, or the runtime cost. This guide walks you through the swap, from a one-line find-and-replace to the closures and arrow functions you’ll want in real code.
Table of Contents
- Introduction to Anonymous Functions
- Why Replace
create_function()with Anonymous Functions? - Syntax and Usage of Anonymous Functions
- Beginner Guide: Simple Replacements
- Intermediate Guide: Using Closures in Callbacks
- Advanced Guide: Advanced Use Cases of Anonymous Functions
- Performance Considerations
- Security Considerations
- Conclusion
Introduction to Anonymous Functions
Anonymous functions, also known as closures, landed in PHP 5.3. They let you define a function without giving it a name. Unlike a regular function, a closure can capture variables from the surrounding scope, which is why you’ll see them used as callbacks, as function arguments, or as small pieces of inline logic.
The syntax looks like a regular function, minus the name:
Example of an Anonymous Function
<?php
// Define an anonymous function and assign it to a variable.
$greet = function($name) {
return "Hello, " . $name;
};
// Call the anonymous function
echo $greet('World'); // Outputs: Hello, WorldYou can pass an anonymous function as an argument, return it from another function, or invoke it on the spot. That flexibility is the whole point: define a small function right where you need it.
Why Replace create_function() with Anonymous Functions?
create_function() built functions at runtime by taking the function body as a string and evaluating it internally. That design carried three real problems:
- Security Risks: Because the body was a string, any unsanitized input concatenated into it opened the door to code injection. It was effectively
eval()wearing a nicer name. - Performance Overhead: Every call had to parse and compile that string at runtime, so you paid a cost each time instead of once at compile time.
- Gone in PHP 8.0: It was deprecated in PHP 7.2 and removed in PHP 8.0. On any modern PHP version, calling it is a fatal error, not a warning.
Anonymous functions have none of these problems. There’s no string to evaluate, so there’s nothing to inject into, and they compile like any other function.
Example of create_function() vs Anonymous Function
<?php
// Old way using create_function
$greetOld = create_function('$name', 'return "Hello, " . $name;');
echo $greetOld('World'); // Outputs: Hello, World
// Modern way using anonymous function
$greetNew = function($name) {
return "Hello, " . $name;
};
echo $greetNew('World'); // Outputs: Hello, WorldSame result, no string evaluation. If you still have create_function() calls in a codebase, they’re the first thing to clear before you move to PHP 8.
Syntax and Usage of Anonymous Functions
Before you start swapping code, get the pieces straight:
- Function Keyword: An anonymous function starts with
function, followed by an optional parameter list and a body. - Parameters: Like a regular function, it takes parameters and returns values.
- Closure Use: It can pull in variables from the surrounding scope with the
usekeyword.
Basic Anonymous Function Example
<?php
// Anonymous function with parameters
$multiply = function($a, $b) {
return $a * $b;
};
echo $multiply(2, 3); // Outputs: 6Two parameters in, product out. Assign it to a variable, pass it around, or return it from another function.
Using use in Anonymous Functions
The handy part is use, which lets the closure grab a variable from the outer scope even though it was never passed in as an argument.
<?php
// Define a variable outside the function
$factor = 2;
// Capture the variable using 'use'
$double = function($number) use ($factor) {
return $number * $factor;
};
echo $double(5); // Outputs: 10Here $factor is captured by value, so the closure sees a copy taken at the moment it was defined. If you need to reflect later changes, capture by reference with use (&$factor).
Since PHP 7.4 you also have arrow functions, which are a shorter closure that captures the outer scope automatically. The same doubling logic reads as $double = fn($number) => $number * $factor;. They’re limited to a single expression, so reach for a full closure when the body needs more than one line.
Beginner Guide: Simple Replacements
In a small project, most of these swaps are mechanical. Find the create_function() call, drop in the equivalent closure.
Example of Simple Replacement
<?php
// Old way using create_function
$callback = create_function('$a, $b', 'return $a + $b;');
echo $callback(3, 4); // Outputs: 7
// New way using anonymous function
$callback = function($a, $b) {
return $a + $b;
};
echo $callback(3, 4); // Outputs: 7The string arguments become real parameters and a real body. Shorter, and there’s no string for anything to sneak into.
Intermediate Guide: Using Closures in Callbacks
The most common place you’ll use closures is as callbacks. PHP’s array functions, array_map(), array_filter(), usort() and friends, all take one.
Example: Using an Anonymous Function with array_map()
<?php
// Array of numbers
$numbers = [1, 2, 3, 4, 5];
// Use an anonymous function to double each number
$doubled = array_map(function($number) {
return $number * 2;
}, $numbers);
print_r($doubled); // Outputs: [2, 4, 6, 8, 10]The function goes straight into array_map(), right next to the data it works on. This is exactly where an arrow function shines too: fn($number) => $number * 2 says the same thing in a line.
Advanced Guide: Advanced Use Cases of Anonymous Functions
Once you’re comfortable, closures open up patterns like encapsulating logic, generating functions on the fly, and writing in a more functional style.
Example: Dynamic Function Creation
<?php
// Create a function that returns a customized greeting
function createGreeter($greeting) {
return function($name) use ($greeting) {
return $greeting . ', ' . $name;
};
}
$helloGreeter = createGreeter('Hello');
echo $helloGreeter('John'); // Outputs: Hello, John
$goodbyeGreeter = createGreeter('Goodbye');
echo $goodbyeGreeter('John'); // Outputs: Goodbye, JohncreateGreeter() returns a closure that captured $greeting at the time it was built. That’s a factory: same shape, different baked-in value each time you call it. It’s the kind of thing create_function() made painful and closures make trivial.
Performance Considerations
Anonymous functions beat create_function() on performance because they’re parsed once at compile time rather than evaluated from a string on every call. That runtime string cost is gone.
That said, a closure is still a function. Creating one inside a tight loop, over and over, adds up. If a hot path matters, define the closure once outside the loop and profile before you assume anything.
Security Considerations
The security angle was the main reason create_function() had to go. Passing executable code as a string is dangerous: if any of that string comes from user input, you’ve handed an attacker a way to run their own code. Closures don’t evaluate strings, so that whole class of injection simply isn’t there.
Switching to closures removes one risk, not all of them. Keep sanitizing input and escaping output at the point of output, especially anywhere user-supplied data touches your logic.
Conclusion
Moving off create_function() isn’t optional if you’re headed to PHP 8. It was removed in 8.0, so the code won’t run until you replace it. Anonymous functions are the drop-in answer: safer, faster, and readable.
Work through your codebase, swap each create_function() call for a closure or an arrow function, and test as you go. Most are one-line changes. When you’re done you’ll have code that runs on modern PHP and reads better than the string-based version ever did.


