views:

118

answers:

3

I've noticed an annoying peculiarity in PHP (running 5.2.11). If one page includes another page (and both contain their own variables and functions), both pages are aware of each others' variables. However, their functions seem to be aware of no variables at all (except those declared within the function).

My question: Why does that happen? How do I make it not happen, or what's a better way to go about this?

An example of what I'm describing follows.

Main page:

<?php
$myvar = "myvar.";
include('page2.php');

echo "Main script says: $somevar and $myvar\n";
doStuff();
doMoreStuff();
function doStuff() {
    echo "Main function says: $somevar and $myvar\n";
}
echo "The end.";
?>

page2.php:

<?php
$somevar = "Success!";

echo "Included script says: $somevar and $myvar\n";

function doMoreStuff() {
    echo "Included function says: $somevar and $myvar\n";
}
?>

The output:

Included script says: Success! and myvar.
Main script says: Success! and myvar.
Main function says: and
Included function says: and
The end.

Both pages output the variables just fine. Their functions do not.
WRYYYYYY

+10  A: 

You need to use global before using outside-defined variables in a function scope:


function doStuff() {
    global $somevar, $myvar;
    echo "Main function says: $somevar and $myvar\n";
}

More detailed explanation provided at: http://us.php.net/manual/en/language.variables.scope.php

As comments & other answers pointed out accurately, globals can be evil. Check out this article explaining just why: http://my.opera.com/zomg/blog/2007/08/30/globals-are-evil

Joel Alejandro
True, yet a bad idea - globals are a poor second to using arguments in the majority of cases. :-)
middaparka
Bad idea, yet it follows the original code's idea. A wiser solution would be to pass the variables as parameters or something like that.
Joel Alejandro
Spooky - was just updating my comment to say that. :-)
middaparka
I can't come to upvote a global variable...
cballou
I'm not saying that is a good solution. Just pointing out a solution that works on a theoretical level. This shouldn't be used on a production stage.
Joel Alejandro
Thanks Joel, this does what I need. See my reply to cballou as to why I can't use arguments in my situation.
Axidos
+5  A: 

While you could be using global variables, it's generally good practice to pass the variables in as parameters to the functions upon calling. This ensures you know exactly what variables a function is expecting for proper execution. This is not a bug, just intended functionality.

$someVar = 'hey';
$myVar = 'you';

doStuff($someVar, $myVar);
doMoreStuff($someVar, $myVar);


function doStuff($somevar, $myvar) {
    echo "Main function says: $somevar and $myvar\n";
}

function doMoreStuff($somevar, $myvar) {
    echo "More function says: $somevar and $myvar\n";
}

Also notice that the variables outside of the function scope do not have to have matching names as the function parameters themselves. This allows you to do things like:

$badVar = 'look at me, im a bad var.';
goodFunction($badVar);

function goodFunction ($goodVar) {
    // output: look at me, im a good var
    echo str_replace('bad', 'good', $goodVar);
}
cballou
+1 for doing the right thing (and taking the time to explain it).
middaparka
The problem with that arises here: I have a lot of files to handle, and globals to record stuff like the right file extensions and directories. So instead of "images/avatars/$userID.jpg", I say $FOLDER['avatars'] . $userID . $FILE_EXT['avatars'] ... I'm not passing that stuff as arguments. Thanks for your reply though.
Axidos
Anyway, you really should consider storing that information in some sort of object structure rather than a global.
Joel Alejandro
Alright, I guess I'll have to look into that. Any advice or links that can start me on the right track? (I learned OOP this Uni semester just finished)
Axidos
A global registry (singleton) could be a good start...
Franz
I guess I'm not sure why you were so quick to dismiss passing the parameters as there's absolutely no reason your function couldn't take a folder name, user id, and file extension as paremeters. This would just be good practice.
cballou
A: 

php has no scoping hierarchy, that is, functions are not aware of each others' (or global) variables. This is a bit weird if you worked with other languages before, but it's essentially a Good Thing, because globals are "evil". The best approach is to avoid them altogether.

stereofrog
This is the behavior in many if not most other languages. Not weird at all.
GZipp