Scope battles

25 11 2006

PHP allows you to define functions inside other functions. Example:

class C {
  function m() {
    function do_magic($x) { return $x + 42; }
    $var_magic = 42;
  }
}

Actually it’s a function inside a method, but it doesn’t matter here. Class C has been added to the global scope, so we can refer to its name and create instances. And do_magic of course is not visible outside of the class definition, right?

echo do_magic(5); // => "Call to undefined function: do_magic()"

Right. OK, let’s make an actual object and call a method.

$c = new C;
$c->m();

All fine. Is $var_magic visible outside of a method?

echo $var_magic; // => null

Of course not. What about a do_magic function?

echo do_magic(5); // => 47

That’s pretty bad, isn’t it? Variables have its local scope inside functions, but functions have only one scope: global. Except when they are methods. But hey, it’s a feature, not a bug, so don’t feel too bad about it.

It hit me today, when I defined a function inside a method and (silly me!) wanted to use a method second time:

$c->m(); // => "Cannot redeclare do_magic()"

I’ve spent few moments to understand what redefining function foo() from file bar.php on line 1 originally defined in the same place meant.

Fatal error: Cannot redeclare do_magic() (previously declared in /var/www/foo.php:42) in /var/www/foo.php on line 42

But I finally got that one. Solutions? Define all your functions outside of other definitions. Or use function_exists.

No rant today, sorry. Go study the Zen of PHP instead.

Advertisements

Actions

Information

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: