9

Is there anyway to for an included file to be used in a parent scope to the one it was called in? The following example is simplified, but does the same job.

In essence, a file will be included by a function, but would like the scope of the included file to be the scope of where the function that included it was called from.

main.php:

<?php
  if(!function_exists('myPlugin'))
  {
    function myPlugin($file)
      {
        if(file_exists($file)
        {
          require $file;
          return true;
        }
        return false;
      }
  }

  $myVar = 'something bar foo';

  $success = myPlugin('included.php');

  if($success)
  {
    echo $myResult;
  }

included.php:

<?php
  $myResult = strlen($myVar);

Thanks in advance,
Alexander.

EDIT: Solution

Well, sort of, thanks to the contributions by Chacha102.
Can be called from within a class now too!

main.php

<?php
  class front_controller extends controller
  {
    public function index_page()
    {
      $myVar = 'hello!';

      // This is the bit that makes it work.
      // I know, wrapping it in an extract() is ugly,
      // and the amount of parameters that you can't change...
      extract(load_file('included.php', get_defined_vars(), $this));

      var_dump($myResult);
    }
    public function get_something()
    {
      return 'foo bar';
    }
  }

  function load_file($_file, $vars = array(), &$c = null)
  {
    if(!file_exists($_file))
    {
      return false;
    }
    if(is_array($vars))
    {
      unset($vars['c'], $vars['_file']);
      extract($vars);
    }
    require $_file;
    return get_defined_vars();
  }

included.php:

<?php
  $myResult = array(
    $myVar,
    $c->get_something()
  );

If you want to reference a method it has to be public, but the result is as expected:

array(2) {
  [0]=>
  string(6) "hello!"
  [1]=>
  string(7) "foo bar"
}

Now, this doesn't really have any practical use, and the only reason I wanted to know how to do this is because I am stubborn. The thought came into my head, and would not let it defeat me :D

<rant>
Thanks to all who contributed. Except the person who boo'd me. It was a simple enough question, and have now figured out that (complicated) solution exists.
Screw whether it "conforms to the PHP way of doing things". Ever told a client "Oh no, we shouldn't do that, it's not the correct way to do things!"? Thought not.
</rant>

Thanks again to Chacha102 :)

zanbaldwin
  • 999
  • 8
  • 28

2 Answers2

5
function include_use_scope($file, $defined_variables)
{
    extract($defined_variables);
    include($file);
}

include_use_scope("file.php", get_defined_vars());

get_defined_vars() gets ALL variables defined in the scope it is called in. extract() takes an array and defines them as local variables.

extract(array("test"=>"hello"));
echo $test; // hello

$vars = get_defined_vars();
echo $vars['test']; //hello

Thus, the desired result is achieved. You might want to strip out the superglobals and stuff from the variables however, as overwriting them might be bad.

Check out this comment for stripping the bad ones out.

In order to get the reverse, you could do something like this:

function include_use_scope($file, $defined_variables)
{
    extract($defined_variables);
    return include($file);
}

extract(include_use_scope("file.php", get_defined_vars()));

include.php

// do stuff
return get_defined_vars();

But all in all, I don't think you are going to get the desired effect, as this was not how PHP was built.

Tyler Carter
  • 60,743
  • 20
  • 130
  • 150
  • How would main.php then get access to included.php's local vars, as in OP's code? – Brock Batsell Feb 06 '10 at 03:31
  • Gah ... Overlooked that part of it. I'll put in my answer that it is only one way, as I believe a two-way operation just isn't going to work. – Tyler Carter Feb 06 '10 at 03:32
  • I came up with a solution that the file can return the defined variables, and then the main file can extract them .. but it seems really hacky and annoying. – Tyler Carter Feb 06 '10 at 03:35
  • This did give me a great idea on how to do it. It's long winded, complicated, and not really necessary. But thanks for your help! – zanbaldwin Feb 06 '10 at 03:55
-1

The only way I know how to is to use the superglobal array.

main.php:

  $GLOBALS['myVar'] = 'something bar foo';

  $success = myPlugin('included.php');

  if($success)
  {
    echo $GLOBALS['myResult'];
  }

included.php:

<?php
  $GLOBALS['myResult'] = strlen($GLOBALS['myVar']);
Brock Batsell
  • 5,786
  • 1
  • 25
  • 27