Jump to content

variable/object/function scoping issue? namespace related?


darrenc
 Share

Recommended Posts


<?php namespace ProcessWire;

class Foo {};
$foo = new Foo;
$foo->message = "hello world";

function print_foo() {
	global $foo;
	print_r($foo);
}

print_r($foo); // success
print_foo(); // nothing

?>

In any template file, or init, the above code doesn't pull $foo into the function's local scope. It seems to not exist even though I'd fully expect it to be there.

Does anyone have insight into why this happens or how I should be approaching it?

Link to comment
Share on other sites

Why not use closures?

function print_foo() use($foo) { // to be able to change $foo use get it by reference &$foo instead
	print_r($foo);
}

One distinction is that with closures $foo will have the value at the moment of function creation, whereas global $foo will have the value of $foo at the time of execution. Often this doesn't matter, but you should be aware.

Also with closures you can reference variables from parent scope. To access even higher scopes, you'll have to use globals.

https://stackoverflow.com/questions/16959576/reference-what-is-variable-scope-which-variables-are-accessible-from-where-and

  • Like 1
Link to comment
Share on other sites

15 hours ago, darrenc said:

I wonder why that is done. 

That's a remnant from times with PHP < 5.4, where the register_globals setting in php.ini was still often set to true. This meant that every GET or POST parameter was added as a global variable of the same name. If programmers were just a tiny bit sloppy and forgot to initialize their global variables with reasonable default values, this lead to security issues since malicious visitors could set their desired values. A simple example would be a PHP script with an authorization check.

Let's suppose our hacker calls it with the URL http://my.broken.site/page.php?auth=1

<?php

// Authorization check
if(is_user_authorized()) {
  // we only set $auth to a truthy value when the check was successful
  $auth = true;
}

if($auth) {
  show_sensitive_content();
}

In that example, $auth isn't set to anything if is_user_authorized fails, so our hacker created a global variable $auth from the GET parameter with a truthy value (1) and that never gets overwritten. He can see our sensitive content. Ouch.

To prevent these kinds of problems, it was good practice to remove all globals before populating your own.

  • Like 4
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...