3

Recently stumbled upon this neat little bug or 'feature' in PHP:

function myCmpFunc($a,$b) {
    function inner($p) {
         // do something
    }
    $inner_a = inner($a);
    $inner_b = inner($b);
    if ($inner_a == $inner_b) return 0;
    return ($inner_a > $inner_b ? -1 : 1);
}

Results in a fatal error "cannot redeclare function inner in ...", when called like this

usort($myArray, 'myCmpFunc');

It works flawlessly when function inner is declared outside of myCmpFunc and/or $myArray has not more than 2 elements ;)

-- edit --

somehow Related: PHP Fatal error: Cannot redeclare function

So here is my question, then: Is it possible to declare functions in local scope?

-- edit 2 --

Maybe, this works well in PHP 5.3 just read it has closures, yeehaa!

Community
  • 1
  • 1
line-o
  • 1,885
  • 3
  • 16
  • 33
  • 3
    Writing code that *compiles* but is *invalid* doesn't constitute a PHP *bug*. – Jason McCreary May 10 '11 at 15:13
  • @jason-mccreary you're absolutely right. Nonetheless, I find it useful to declare functions in functions and have them in outer function's local scope. Not in PHP, as functions are always in global scope, I learned. Have to use methods, then. – line-o May 11 '11 at 06:29

4 Answers4

2

As of PHP v5.3 one can now write it the nice way:

$myCmpFunc = function ($a, $b) {
    static $inner = function ($element) {
         return $element['width']; // just as an example
    };
    $inner_a = $inner($a);
    $inner_b = $inner($b);
    if ($inner_a == $inner_b) return 0;
    return ($inner_a > $inner_b ? -1 : 1);
};
usort($anArray, $myCmpFunc);
line-o
  • 1,885
  • 3
  • 16
  • 33
2

function inner($p) is defined each time that function myCmpFunc($a,$b) is executed. Furthermore, the inner function is visible outside function myCmpFunc($a,$b) after that (which pretty much takes the sense out of allowing nested function definitions). That's why you get a duplicate definition error when you call the outer function a second time.

To work around this, check whether function_exists in the body of function myCmpFunc($a,$b).

Oswald
  • 31,254
  • 3
  • 43
  • 68
1

The function declaration is inside myCmpFunc, and because usort would call myCmpFunc for each element of an array, what happens is similar to declaring a function N times.

Camilo Díaz Repka
  • 4,805
  • 5
  • 43
  • 68
1

The issue is you must call the outer function before using the inner function. As per this answer to a similar question Can I include a function inside of another function?

So your use of inner($a); is not valid.

Community
  • 1
  • 1
Jordan
  • 4,928
  • 4
  • 26
  • 39