Requiring code within a function designed to be global

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Requiring code within a function designed to be global

Post by Ollie Saunders »

Code: Select all

// GlobalCode.php
$globalVar = 10;
function globalFunction()
{
    global $globalVar;
    return $globalVar * 2;
}

Code: Select all

// CallGlobalCode.php
function something()
{
    require_once 'GlobalCode.php'; // GlobalCode is only needed if this function is used
    return globalFunction();
}

Code: Select all

// TestOfCallGobalCode.php
require_once 'CallGlobalCode.php';
$this->assertEqual(something(), 20);
// fails with undefined $globalVar
This is because GlobalCode.php was required inside something() function making the variable definition local to the function rather than global as intended. The call to globalFunction() inside something() works because function definitions are always global.

Constraints:
  • You are not allowed to modify GlobalCode.php
  • In CallGlobalCode.php, GlobalCode.php must only be required when it is needed i.e. when something is called so just sticking require_once 'GlobalCode.php' outside of something() is not acceptable.
So the question is how can I fool PHP into thinking GlobalCode.php is in global scope even when it is being called from inside a function without modifying GlobalCode.php itself?
User avatar
onion2k
Jedi Mod
Posts: 5263
Joined: Tue Dec 21, 2004 5:03 pm
Location: usrlab.com

Post by onion2k »

Yuck. Horrible code. Globals suck.

If you really must use a global like this, write it directly to the $GLOBALS array. EG

Code: Select all

// GlobalCode.php
$GLOBALS['globalVar'] = 10;
function globalFunction()
{
    return $GLOBALS['globalVar'] * 2;
}
Thats the only way to do it.

Well, I suppose you could do file_get_contents("GlobalCode.php"), modify it, then eval the resulting string. I wouldn't though.
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

The globals are defined in phputf8 written by Harry Fuecks. I certainly wouldn't write a library in this way (and I'm not) but considering my library depends on phputf8 I don't want to have to modify phputf8 in order for it to work with mine hence constrant
I wrote:You are not allowed to modify GlobalCode.php
If you really must use a global like this, write it directly to the $GLOBALS array. EG
Breaks the first constrant and is obviously what I would do were it not there.
Well, I suppose you could do file_get_contents("GlobalCode.php"), modify it, then eval the resulting string. I wouldn't though.
Yes I did consider that but I happen to agree with you, its pretty manky.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

Code: Select all

function something()
{
	global $globalVar;
	require_once 'GlobalCode.php'; // GlobalCode is only needed if this function is used
	return globalFunction();
}
nevertheless bad solution.
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Volka; awesome!
Can't believe I didn't think of it myself.
nevertheless bad solution.
Its a dirty hack yes but its a hell of a lot better than the alternatives. Thanks you.
harry_f
Forum Newbie
Posts: 1
Joined: Wed Oct 04, 2006 5:39 am

Post by harry_f »

Re this bug report - understood and considering fixes - not decided yet. Hadn't foreseen that scenario.
The globals are defined in phputf8 written by Harry Fuecks. I certainly wouldn't write a library in this way (and I'm not) but considering my library depends on phputf8 I don't want to have to modify phputf8 in order for it to work with mine hence constrant
The reason for placing the lookup table globally is for performance - ideally it should only be created once per request. For similar reasons phputf8 prefers functions over classes - anything that save a few milliseconds. Normally abstractions are worth it but when it comes to replacing something as fundamental as PHP's string functions, which tend to get used all over, with userland functions, performance is worth considering.

Also be careful with $GLOBALS - http://www.hardened-php.net/advisory_202005.79.html
User avatar
Ollie Saunders
DevNet Master
Posts: 3179
Joined: Tue May 24, 2005 6:01 pm
Location: UK

Post by Ollie Saunders »

Re this bug report - understood and considering fixes - not decided yet. Hadn't foreseen that scenario.
That be mi bug report yarr :)
Interesting. How about setting the global inside a function:

Code: Select all

function setLookUps() {
    global $UTF8_UPPER_ACCENTS, $UTF8_LOWER_ACCENTS;
    $UTF8_UPPER_ACCENTS = array(/* lookup */);
    $UTF8_LOWER_ACCENTS = array(/* lookup */);
}
which avoids using $GLOBALS.
For similar reasons phputf8 prefers functions over classes - anything that save a few milliseconds.
Well OK but won't those most concerned with performance be running opcode caches that will all but obliterate that problem?
Post Reply