3

This is a bit of a peculiar one; I don't think this is in fact possible, however the SO community has surprised me time and time again; so here goes.

Given in PHP; I have the following snippet:

$path = 'path/to/file.php';
$buffer = call_user_func(function() use($path){
    ob_start();
    require $path;
    return ob_get_clean();
});

When included, path/to/file.php will have $path in it's scope. Is there any way to prevent this variable from being available in the context of the included file?

For instance, given unset() returned the value of the variable it was unsetting, I could do:

require unset($path);

But of course that doesn't work.


For those curious, I'm trying to prevent $path from inheriting a value from the include-er.

"Security-by-obfuscation" is a consideration I made; passing something like $thisIsThePathToTheFileAndNobodyBetterUseThisName, but that seems a bit silly and still isn't foolproof.

For other "reserved" variables that should be inherited, I've already went with extract() and unset():

$buffer = call_user_func(function() use($path, $collection){
    extract($collection);
    unset($collection);
    ob_start();
    // ...

Edit:

What I finally went with:

$buffer = call_user_func(function() use(&$data, $registry){
    extract($registry, EXTR_SKIP);
    unset($registry);
    ob_start();
    // only $data and anything in $registry (but not $registry) are available
    require func_get_arg(0);
    return ob_get_clean();
}, $viewPath);

Perhaps my question was a bit misleading, through my use of use() to pass variables into the anonymous function scope; passing arguments was an option I neglected to mention.

Regarding @hakre and use() + func_get_args():

$var = 'foo';
$func = function() use($var){
    var_dump(func_get_args());
};
$func(1, 2, 3);

/* produces
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
}
Dan Lugg
  • 20,192
  • 19
  • 110
  • 174

3 Answers3

2

You can do this with the help of an additional function. In the example I used echo instead of require:

$path = 'hello';

function valStore($value = null) {
    static $s = null;
    if ($value !== null)
        $s = $value;
    else
        return $s;
}

valStore($path);
unset($path); # and gone
echo valStore();
hakre
  • 193,403
  • 52
  • 435
  • 836
2

Use func_get_arg() instead of using traditional function arguments:

$buffer = call_user_func(function() {
    ob_start();
    require func_get_arg(0);
    return ob_get_clean();
}, $path);
Andrew Moore
  • 93,497
  • 30
  • 163
  • 175
1

You can use something like this:

$path = 'path/to/file.php';
function getPath() {
    global $path;
    $p = $path;
    unset($path);
    return $p;
}
$buffer = call_user_func(function() {
    ob_start();
    require getPath();
    return ob_get_clean();
});
useraged
  • 1,706
  • 17
  • 34
  • Thanks Berk Demirkir - So from what I'm gathering between the approach you and @hakre took, the only way is to define a function to store/fetch the value. Darn, my global scope was so clean too. Defining one for this one-off will be like painting an orange streak down an otherwise white wall. – Dan Lugg Jul 27 '11 at 05:42
  • @hakre: Sorry `use` keyword is for closures. Copy/paste mistake. Corrected – useraged Jul 27 '11 at 06:04
  • @Berk: Why not just `require $GLOBALS['path'];`? – hakre Jul 27 '11 at 06:10
  • @hakre: It's just my personal preference. I don't like using $GLOBALS. Generally i don't use globals :) – useraged Jul 27 '11 at 06:37
  • @Berk: I meant not generally but in the suggestion you just make: Why create a function to access a global variable? – hakre Jul 27 '11 at 06:48
  • @hakre & Berk - In my haste I also neglected to mention that this process is occurring in a method; the purpose for `call_user_func()` is only to escape from the method's scope, thus preventing the passing of `$this` into the required file. `$GLOBALS` would not have been an option, and I also would have needed to either define the function outside the method, or do a `function_exists()` everytime. – Dan Lugg Jul 28 '11 at 01:11
  • @TomcatExodus: That affects global then. – hakre Jul 28 '11 at 08:17