在PHP中的全局命名空间的上下文中运行功能块

在PHP中的全局命名空间的上下文中运行功能块

问题描述:

So the senario is that I want to have a custom function for requiring libraries. Something like:

define('E_ROOT', str_replace('//','/',dirname(__FILE__)));
/* ... */
function e_load($fn, $allowReloading = FALSE) {
    $inc = E_ROOT.'/path/here/'.$fn.'.php';
    if($allowReloading)
        require $inc; // !!!
    else
        require_once $inc; // !!!
}

The problem being that require and require_once will load the files into the namespace of the function, which doesn't help for libraries of functions, classes, et cetera. So is there a way to do this?

(Something avoiding require and require_once altogether is fine, as long as it doesn't use eval since it's banned on so many hosts.)

Thanks!

所以senario是我想要一个自定义函数来要求库。 类似于: p>

  define('E_ROOT',str_replace('//','/',dirname(__ FILE __))); 
 / * ... * /  
 
函数e_load($ fn,$ allowReloading = FALSE){
 $ inc = E_ROOT。'/ path / here /'.$ fn。'。php'; 
 if($ allowReloading)
 require $ inc;  // !!! 
 else 
 require_once $ inc;  // !!! 
} 
  code>  pre> 
 
 

问题是 require code>和 require_once code>将加载文件 进入函数的命名空间,这对函数库,类等没有帮助。 有没有办法做到这一点? p>

(完全避免 require code>和 require_once code>的东西很好,只要它不使用 eval code >因为它被许多主机禁止。) p>

谢谢! p> div>

Technically include() is meant to act as though you're inserting the text of included script at that point in your PHP. Thus:

includeMe.php:
<?php
    $test = "Hello, World!";
?>

includeIt.php:
<?php
    include('includeMe.php');
    echo $test;
?>

Should be the exact same as:

<?php
    /* INSERTED FROM includeMe.php */
    $test = "Hello, World!";
    /* END INSERTED PORTION */
    echo $test;
?>

Realizing this, the idea of making a function for dynamically including files makes about as much sense (and is about as easy to do) as having dynamic code all-together. It's possible, but it will involve a lot of meta-variables.

I'd look into Variable Variables in PHP as well as the get_defined_vars function for bringing variables into the global scope. This could be done with something like:

<?php
define('E_ROOT', str_replace('//','/',dirname(__FILE__)));
/* ... */
function e_load($fn, $allowReloading = FALSE) {

    $prev_defined_vars = get_defined_vars();

    $inc = E_ROOT.'/path/here/'.$fn.'.php';
    if($allowReloading)
        require $inc; // !!!
    else
        require_once $inc; // !!!

    $now_defined_vars = get_defined_vars();

    $new_vars = array_diff($now_defined_vars, $prev_defined_vars);

    for($i = 0; $i < count($new_vars); $i++){
        // Pull new variables into the global scope
        global $$newvars[$i];
    }
}
?>

It may be more convenient to just use require() and require_once() in place of e_load()

Note that functions and constants should always be in the global scope, so no matter where they are defined they should be callable from anywhere in your code.

The one exception to this is functions defined within a class. These are only callable within the namespace of the class.

EDIT:

I just tested this myself. Functions are declared in the global scope. I ran the following code:

<?php
function test(){
    function test2(){
        echo "Test2 was called!";
    }
}

//test2(); <-- failed
test();
test2(); // <-- succeeded this time
?>

So the function was only defined after test() had been run, but the function was then callable from outside of test(). Therefore the only thing you should need to pull into the global scope are your variables, via the script I provided earlier.

require_once E_ROOT.$libName.'.php';

KISS

Instead of doing this...

$test = "Hello, World!";

... you could consider doing this ...

$GLOBALS[ 'test' ] = "Hello, World!";

Which is safe and consistent in both local function context, and global include context. Probably not harmful to visually remind the reader that you are expecting $test to become global. If you have a large number of globals being dragged in by your libraries maybe there's justification for wrapping it in a class (then you have the benefit of spl_autoload_register which kind of does what you are doing anyhow).