запустить функциональный блок в контексте глобального пространства имен в PHP - PullRequest
1 голос
/ 03 октября 2010

Таким образом, сенарио состоит в том, что я хочу иметь пользовательскую функцию для запроса библиотек. Что-то вроде:

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; // !!!
}

Проблема в том, что require и require_once будут загружать файлы в пространство имен функции, что не помогает для библиотек функций, классов и так далее. Так есть ли способ сделать это?

(Что-то, избегающее require и require_once в целом, хорошо, если оно не использует eval, поскольку оно запрещено на многих хостах.)

Спасибо!

Ответы [ 3 ]

2 голосов
/ 03 октября 2010

Технически include() должен действовать так, как будто вы вставляете текст включенного скрипта в тот момент в вашем PHP. Таким образом:

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

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

Должно быть точно таким же, как:

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

Понимая это, идея создания функции для динамического включения файлов имеет столько же смысла (и почти так же легко сделать), как и динамический код в целом. Это возможно, но в нем будет много метапеременных.

Я бы посмотрел на Переменные в PHP, а также на функцию get_defined_vars для переноса переменных в глобальную область видимости. Это можно сделать с помощью чего-то вроде:

<?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];
    }
}
?>

Может быть удобнее просто использовать require() и require_once() вместо e_load()

Обратите внимание, что функции и константы должны всегда находиться в глобальной области видимости, поэтому независимо от того, где они определены, они должны вызываться из любого места в вашем коде.

Единственное исключение - это функции, определенные в классе. Они могут быть вызваны только в пространстве имен класса.

EDIT:

Я только что проверил это сам. Функции объявлены в глобальной области видимости. Я запустил следующий код:

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

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

Таким образом, функция была определена только после запуска test(), но затем функция могла вызываться извне test(). Таким образом, единственное, что вам нужно включить в глобальную область видимости - это ваши переменные с помощью сценария, который я предоставил ранее.

0 голосов
/ 16 мая 2013

Вместо этого ...

$test = "Hello, World!";

... вы могли бы подумать об этом ...

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

Что является безопасным и согласованным как в контексте локальной функции, так и в контексте глобального включения. Вероятно, не вредно визуально напомнить читателю, что вы ожидаете, что $ test станет глобальным. Если ваши библиотеки перетаскивают большое количество глобальных переменных, возможно, есть оправдание для того, чтобы обернуть их в класс (тогда у вас есть преимущество от spl_autoload_register, который в любом случае делает то, что вы делаете).

0 голосов
/ 03 октября 2010
require_once E_ROOT.$libName.'.php';

KISS

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...