Можно ли получить список определенных пространств имен - PullRequest
30 голосов
/ 08 марта 2011

HI там,

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

, если file 1 has namespace FOO и file 2 has namespace BAR

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

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

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

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

Ответы [ 2 ]

38 голосов
/ 08 марта 2011

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

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

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

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

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

<?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] => 

        )
)
14 голосов
/ 08 марта 2011

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

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

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

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

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

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

<?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");
}

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

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

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

После этого:

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