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

Всем привет,

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

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

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

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

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

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

Во-первых, чтобы увидеть, существует ли класс, используется 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] => ) ) 

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

Похоже, что 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 ); } } ); 

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

После этого:

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