Подтвердить что ты не робот

Возможно ли получить список определенных пространств имен

HI,

Мне было интересно, есть ли способ в php 5.3+ получить список определенных пространств имен в приложении. поэтому

если   file 1 has namespace FOO а также   file 2 has namespace BAR

Теперь, если я включаю файл 1 и файл 2 в файл 3 id, как знать с каким-то вызовом функции, загружаются пространство имен FOO и BAR.

Я хочу достичь этого, чтобы убедиться, что модуль в моем приложении загружен, прежде чем проверять, существует ли класс (с is_callable).

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

Надеюсь, вы получите эту идею. и что я пытаюсь достичь

4b9b3361

Ответ 1

Во-первых, чтобы увидеть, существует ли класс, используется class_exists.

Во-вторых, вы можете получить список классов с пространством имен, используя get_declared_classes.

В простейшем случае вы можете использовать это, чтобы найти подходящее пространство имен из всех объявленных имен классов:

function namespaceExists($namespace) {
    $namespace .= "\\";
    foreach(get_declared_classes() as $name)
        if(strpos($name, $namespace) === 0) return true;
    return false;
}

Другой пример: script создает иерархическую структуру массива объявленных пространств имен:

<?php
namespace FirstNamespace;
class Bar {}

namespace SecondNamespace;
class Bar {}

namespace ThirdNamespace\FirstSubNamespace;
class Bar {}

namespace ThirdNamespace\SecondSubNamespace;
class Bar {}

namespace SecondNamespace\FirstSubNamespace;
class Bar {}

$namespaces=array();
foreach(get_declared_classes() as $name) {
    if(preg_match_all("@[^\\\]+(?=\\\)@iU", $name, $matches)) {
        $matches = $matches[0];
        $parent =&$namespaces;
        while(count($matches)) {
            $match = array_shift($matches);
            if(!isset($parent[$match]) && count($matches))
                $parent[$match] = array();
            $parent =&$parent[$match];

        }
    }
}

print_r($namespaces);

дает:

Array
(
    [FirstNamespace] => 
    [SecondNamespace] => Array
        (
            [FirstSubNamespace] => 
        )
    [ThirdNamespace] => Array
        (
            [FirstSubNamespace] => 
            [SecondSubNamespace] => 

        )
)

Ответ 2

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

Похоже, что OP имеет модульную систему, которую ему нужно знать, если какой-либо конкретный модуль загружен до разрешения вызова.

Во-первых, я хотел бы сказать, что использование пространств имен просто для объявления активных модулей - это ИМО, злоупотребляющих тем, для чего они предназначены. Если вы будете следовать назначению имен на букву, ваша структура может выглядеть примерно так:

Вся ваша система должна находиться в своем собственном пространстве имен. Позвоните в это пространство имен System. Тогда модули, вероятно, будут находиться под пространством имен System\Module. Тогда, в зависимости от сложности, возможно, что каждый модуль может иметь пространство имен под System\Module. Принимая ваши примеры, System\Module\FOO и System\Module\BAR.

Теперь давайте перейдем к созданию модульной системы, которая регистрируется при загрузке.

Во-первых, нам нужно место для регистрации. Позвольте называть это System\Module\Registry, и, поскольку, вероятно, будет много разных реестров, он будет реализовывать System\iRegistry. Для краткости я публикую только System\Module\Registry. По всей вероятности, он также реализует какую-то глобальную модель согласованности, такую ​​как singleton, но я тоже не показываю. Вот он:

<?php
namespace System\Module
{
    class Registry extends System\Registry
    {
        protected $registered = array();

        public function register( $name=null )
        {
            $this->registered[] = $name;
        }

        public function isRegistered( $module )
        {
            // Code to find module
        }

        public function getModule( $module )
        {
            // Code to find module

            // OR, if you can't find it...
            throw new ModuleNotRegisteredException("Module named \"{$module}\" could not be found in the registry.");
        }
    }
}
?>

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

namespace System\Module\FOO
{
    // Load this module
    $system->module->register("FOO");
}

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

spl_autoload_register(
    function ($className)
    {
        // Code to load files.
        // Once loaded register our modules.
        if( $namespace = "System\\Module" )
        {
            $system->module->register( $classname );
        }
    }
); 

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

После этого:

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