Nested functions in PHP and why you should avoid them!

This week, I reviewed the code of a website. The website was using some code snippets. In one of those snippets, I’ve found a PHP nested function. The code didn’t work as expected. Not because of the nested function, but it gave me the idea for this blog post. I cannot share the original code, but I hope I can give you an example on how nested function work and why you probably shouldn’t use them.

What is a nested function?

A nested function in PHP is a function declared in the body of another function. We could call them “outer function” and “inner function” or “nested function”. Here is an example for such a nested function:

function multiplyAllByTwo( $array ) {
	function multiplyByTwo( $value ) {
		return $value * 2;
	}

	return array_map( 'multiplyByTwo', $array );
}

We have a function to process an array and multiple all its values by 2. By using a function here, we could “potentially” do the same things for multiple arrays. Inside that function, we declare another helper function, that multiplies a given value by 2. This is the nested function. It is passed to an array_map() call, which will apply it to every entry of the $array. So when we throw in an array, we get back the array with all values multiplied by 2:

$inputArray = [ 1, 2, 3, 4, 5 ];
$resultArray = multiplyAllByTwo( $inputArray );
print_r( $resultArray );
/*
Array
(
	[0] => 2
    [1] => 4
    [2] => 6
    [3] => 8
    [4] => 10
)
*/

That’s great, so what’s the issue? Well, let’s try to multiply the resulting array again:

$inputArray   = [ 1, 2, 3, 4, 5 ];
$resultArray  = multiplyAllByTwo( $inputArray );
$resultArray2 = multiplyAllByTwo( $resultArray );
print_r( $resultArray );
print_r( $resultArray2 );

What are we expecting when running these two calls? A second array with all values multiplied by 2 again, right? But what to we get instead?

PHP Fatal error:  Cannot redeclare multiplyByTwo() ...

When we call the function a second time, we get a fatal error, because the function cannot be declared with the same name again. So a nested function only work for an “out function”, that is only run ones. So what could we do instead?

Don’t use a nested function

The easiest way would be to move the nested function out of the other function and just declare it in the global namespace as well:

function multiplyAllByTwo( $array ) {
	return array_map( 'multiplyByTwo', $array );
}

function multiplyByTwo( $value ) {
	return $value * 2;
}

Now we can safely run the (previously) outer function twice:

$inputArray = [ 1, 2, 3, 4, 5 ];
$resultArray1 = multiplyAllByTwo( $inputArray );
$resultArray2 = multiplyAllByTwo( $resultArray1 );
print_r( $resultArray1 );
print_r( $resultArray2 );
/*
Array
(
	[0] => 2
    [1] => 4
    [2] => 6
    [3] => 8
    [4] => 10
)
Array
(
	[0] => 4
    [1] => 8
    [2] => 12
    [3] => 16
    [4] => 20
)
*/

Now we get the result we want. But we also pollute the global namespace with many functions. And we need to make sure, that we don’t use the same function name for these different helper function. As an alternative, you can also declare the function to a variable and use this instead of the function’s name string. But then you would again do this inside the outer function, as otherwise that variable would not be available, or you would need to make the variable available inside the function using the global keyword. Both not really nice solution, and that’s why I don’t even want to show code snippets for them ?

So when you don’t really need a globally declared function, how can you solve it then? There is another way to do this.

Use an anonymous function

An anonymous function is often used in combination with functions like array_map() and similar function. Our code would look like this:

function multiplyAllByTwo( $array ) {
	return array_map( function ( $value ) {
		return $value * 2;
	}, $array );
}

In this example, we declare the function at the moment we need it. This also eliminates the need to come up with a nice name, and we all know that naming things is one of the “two hard things in programming” ?

With PHP 7.4 and higher, you can even use a nice little arrow function that lets you write a single line function for this snippet:

function multiplyAllByTwo( $array ) {
	return array_map( fn( $value ) => $value * 2, $array );
}

Looks nice, right?

Conclusion: when to use which?

I’d recommend to never use a nested function! While in other programming languages it might be a common pattern, in PHP it can easily lead to fatal errors and testing/debugging issues.

When you possibly need the logic of the “inner function” for multiple “outer functions”, then declare the function with a name, either in the global namespace, or in a PHP class.

When you need that logic only for this specific “outer function”, or it is really very basic like in this example, you can use an anonymous function or even an arrow function.

Posted by

Bernhard is a full time web developer who likes to write WordPress plugins in his free time and is an active member of the WP Meetups in Berlin and Potsdam.

Leave a Reply

Your email address will not be published. Required fields are marked *