views:

442

answers:

6

Following is code snippet :

function something() {
$include_file = 'test.php';
if ( file_exists($include_file) ) {
    require_once ($include_file);
//      global $flag;
//        echo 'in main global scope flag='.$flag;
    test();
   }
}

something();

exit;

 //in test.php

$flag = 4;
function test() {
   global $flag;

   echo '<br/>in test flag="'.$flag.'"';
   if ($flag) {
       echo 'flag works';
     //do something
   }
}

The above code snippet, echoes 'global scope' $flag value properly but doesnt recognises the $flag with value 4, assumes null value for $flag . Please point out what is wrong in accessing that $flag global variable.

Thanks in advance, Anitha

+2  A: 

The line likely giving you problems is this one: echo 'global scope flag'=$flag;

Change it to: echo 'global scope flag = '.$flag;

Edit: Now that you have edited you code snippet to by wrapping your code in the something() function, the problem becomes more clear. I think what is happening here is that the when you initialize $flag with $flag = 4;, it's scope is within the something() method.

Try placing $flag = 4; above/before the line function something() {. Then all will be right with the world.

Bart
hi, thanks for the response.that was a typo, corrected it.But the original problem is still there.
Anitha
OK, well with that line corrected, I see no other problems with the code you have posted. Your problem is within the `test()` method right? What happens if you access test.php directly? Same error?
Bart
A: 

Shouldn't echo 'global scope flag'=$flag; be echo 'global scope flag =' . $flag;

I received a different error. Which helped me fix the issue quickly.

Parse error: parse error, unexpected '=', expecting ',' or ';' in D:\Websites (Apache)\Test Site1\test.php on line 6

Shoban
A: 

Just do something like this:

$myFlag = getFlag(); 
echo $myFlag; // output: whatever


// test.php 

$flag = 'whatever'; 

function getFlag(){
    global $flag;   
    return $flag; 
}

I would never set a variable in one script and call it from another file. this will cause extreme confusion down the road. Even my solution isn't the best. I would do this as a full blown class w/ ideally.

bonez
no, am echoing $flag after require, which means by then $flag has been defined. isnt it ?
Anitha
+1  A: 

$flag = 4; is not in the global scope.

If the include occurs inside a function within the calling file, then all of the code contained in the called file will behave as though it had been defined inside that function.

-- PHP Manual page for include, which also applies for include_once, require, and require_once

I'm going to make a guess that the error you're getting is on the if ($flag) line, because at that point, $flag is uninitialized, because the global $flag variable has never been assigned a value.

Incidentally, echo 'global scope flag='.$flag; isn't displaying the global flag either, as you need a global $flag; in that function to display the global copy, which also has the side effect of making $flag = 4; affect the global copy in the included file.

R. Bemrose
+4  A: 

You are running in a problem here simply because the way PHP is currently interpreting your file. You have nested functions.

Here is how your code currently executes:

function something() {
    $include_file = 'test.php';
    if ( file_exists($include_file) ) {
        //require_once ($include_file);

        $flag = 4;
        function test() {
           global $flag;

           echo '<br/>in test flag="'.$flag.'"';
           if ($flag) {
               echo 'flag works';
             //do something
           }
        }

        //end require_once ($include_file);

        test();
    }
}

something();

exit;

As you can see, when you assign the value of 4 to $flag ($flag = 4), you are within the scope of the function something(), not within the global scope.

In test(), since you declare $flag as global within that function, $flag is a totally different variable, global to the whole script.

In order to avoid this problem, use the superglobal $GLOBALS. It's faster than using global anyway, and that way you don't get mingled in scoping issues as the ones above:

function something() {
    $include_file = 'test.php';
    if ( file_exists($include_file) ) {
        //require_once ($include_file);

        $GLOBALS['flag'] = 4;
        function test() {
           global $flag;

           echo '<br/>in test flag="'.$GLOBALS['flag'].'"';
           if ($GLOBALS['flag']) {
               echo 'flag works';
             //do something
           }
        }

        //end require_once ($include_file);

        test();
    }
}

something();

echo $flag; //echos 4

exit;
Andrew Moore
+1, just for completeness: `global $flag; require_once ($include_file);` would also do the trick. But this whole global/function/require thingy seems hackish to me, anyway.
VolkerK
Actually, while this is mostly correct, the test() function is moved outside of the something() function: "all functions and classes defined in the included file have the global scope." http://php.net/include
R. Bemrose
But the same happens if you write the function definition literally into the "outer" function. So the example is correct in this point, too.
VolkerK
@VolkerK: Whoops, so they are. I guess I've never used them that way.
R. Bemrose
@R. Bemrose: Actually, PHP5.3 has closures now, so the documentation is outdated on this subject: http://php.net/closures . Even if so, `$flag = 4` is not moved into global scope.
Andrew Moore
A: 

Since your original question has already been answered let me suggest another approach that avoids global variables all together.
You seemingly have a function + a default value that you set as a global variable. You can also define default values for function parameters.

<?php // test.php
function test($flags=4) {
  echo '<br/>in test flag="'.$flags.'"';
  if ($flags!=0) {
    echo ' flag works';
  }
}

No global variable, but you can still call test() without a parameter and the function will use the default value - which you can overwrite by passing the parameter.

function something() {
  $include_file = 'test.php';
  if ( file_exists($include_file) ) {
    require_once ($include_file);
    echo "\nwithout parameter: "; test();
    echo "\nwith a parameter: "; test(16);
  }
}
something();
exit;

prints

without parameter: <br/>in test flag="4" flag works
with a parameter: <br/>in test flag="16" flag works

That's not exactly the same behavior but it may be what you wanted in the first place....

edit: Another point could be the

if ( file_exists($include_file) ) {
  require_once ($include_file);

construct you're using. I don't have a strong opinion (or any strong evidence ;-)) on that but you might want to consider using

$something = include $include_file;
if ( false!==$something ) { /* error handling here... */ }

instead. include "returns" false if php can't include the file. All that's required for this to work is that the included file doesn't explicitly return FALSE. This might be cache friendlier (e.g. when using something like APC). But again: I have no proof for this at hand, just a hunch. At least it gives your code a chance to handle an error "gracefully".

VolkerK