php 是否可以获取已定义命名空间的列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5225971/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
is it possible to get list of defined namespaces
提问by DonSeba
HI there,
你好呀,
I was wondering if there is a way in php 5.3+ to get a list of defined namespaces within an application. so
我想知道 php 5.3+ 中是否有一种方法可以获取应用程序中已定义命名空间的列表。所以
if
file 1 has namespace FOO
and
file 2 has namespace BAR
如果
file 1 has namespace FOO
和
file 2 has namespace BAR
Now if i include file 1 and file 2 in file 3 id like to know with some sort of function call that namespace FOO and BAR are loaded.
现在,如果我在文件 3 中包含文件 1 和文件 2,id 想通过某种函数调用知道命名空间 FOO 和 BAR 已加载。
I want to achieve this to be sure an module in my application is loaded before checking if the class exists ( with is_callable ).
我想实现这一点,以确保在检查类是否存在之前加载我的应用程序中的模块(使用 is_callable )。
If this is not possible i'd like to know if there is a function to check if a specific namespace is defined, something like is_namespace().
如果这是不可能的,我想知道是否有一个函数来检查是否定义了特定的命名空间,例如 is_namespace()。
Hope you get the idea. and what i'm trying to achieve
希望你明白。以及我正在努力实现的目标
回答by Hamish
Firstly, to see if a class exists, used class_exists
.
首先,要查看一个类是否存在,使用class_exists
.
Secondly, you can get a list of classes with namespaceusing get_declared_classes
.
其次,你可以得到的类的列表与命名空间的使用get_declared_classes
。
In the simplest case, you can use this to find a matching namespace from all declared class names:
在最简单的情况下,您可以使用它从所有声明的类名中找到匹配的命名空间:
function namespaceExists($namespace) {
$namespace .= "\";
foreach(get_declared_classes() as $name)
if(strpos($name, $namespace) === 0) return true;
return false;
}
Another example, the following script produces a hierarchical array structure of declared namespaces:
另一个示例,以下脚本生成已声明命名空间的分层数组结构:
<?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);
Gives:
给出:
Array
(
[FirstNamespace] =>
[SecondNamespace] => Array
(
[FirstSubNamespace] =>
)
[ThirdNamespace] => Array
(
[FirstSubNamespace] =>
[SecondSubNamespace] =>
)
)
回答by Kevin Peno
I know this question already has an answer, but I wanted to provide a more realistic solution to what I believe your problem is. Had I had more time yesterday when I made my comment I would have posted this. Sorry that I didn't.
我知道这个问题已经有了答案,但我想为我认为您的问题提供一个更现实的解决方案。如果我昨天发表评论时有更多时间,我会发布这个。抱歉我没有。
It sounds like OP has a module system that he needs to know if a particular module is loaded prior to allowing a call to it.
听起来 OP 有一个模块系统,他需要知道在允许调用之前是否加载了特定模块。
First, I'd like to say that using namespaces simply to declare modules active is, IMO, abusing what they are for. If you follow the purpose of namespacing to the letter, your structure might look more like this:
首先,我想说,仅使用命名空间来声明模块处于活动状态,IMO 滥用了它们的用途。如果您遵循命名空间的目的,您的结构可能看起来更像这样:
Your entire system should be in its own namespace. Let's call that namespace System
. Then, modules would likely be under the System\Module
namespace. Then, depending on the complexity, it would be possible that each module might have a namespace under System\Module
. Taking your examples, System\Module\FOO
and System\Module\BAR
.
你的整个系统应该在它自己的命名空间中。让我们称其为 namespace System
。然后,模块可能位于System\Module
命名空间下。然后,根据复杂性,每个模块可能在System\Module
. 以你的例子为例,System\Module\FOO
和System\Module\BAR
。
Now, let's get into making a module system that registers itself on load.
现在,让我们开始制作一个在加载时自行注册的模块系统。
First, we need a place to register to. Let's call that System\Module\Registry
and, since there are likely to be a lot of different registries, it will implement the System\iRegistry
. For brevity, I'm only posting System\Module\Registry
. In all likelihood, it will also implement some sort of global consistency model, like a singleton, but I'm not showing that either. Here it is:
首先,我们需要一个注册的地方。让我们称之为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.");
}
}
}
?>
Now, in each module you'd need to call this register function when the file is loaded. There are a couple of ways to do this. The first is to have some code in your module's namespace that run on load similar to typical proceedural code:
现在,在每个模块中,您需要在加载文件时调用此注册函数。有几种方法可以做到这一点。第一个是在你的模块的命名空间中有一些代码在加载时运行,类似于典型的程序代码:
namespace System\Module\FOO
{
// Load this module
$system->module->register("FOO");
}
The above would mean code duplication though. You might also use autoload for this instead, that way the "registering" code is all in one place. Here's a very basic concept of doing that:
以上将意味着代码重复。您也可以为此使用自动加载,这样“注册”代码就在一个地方。这是一个非常基本的概念:
spl_autoload_register(
function ($className)
{
// Code to load files.
// Once loaded register our modules.
if( $namespace = "System\Module" )
{
$system->module->register( $classname );
}
}
);
Another possible way of doing this would be to define an interface for modules with a specific function for registering when the module is initialized. This, however, means the module needs to be loaded first and might cause it's own issues depending on your needs.
另一种可能的方法是为具有特定功能的模块定义一个接口,用于在模块初始化时进行注册。但是,这意味着需要首先加载模块,并且可能会根据您的需要导致它自己的问题。
After doing this:
这样做之后:
- you have a consistent namespace for modules to live in
- you have a consistent interface which allows any module to know how to register itself
- you can easily expand the module or registry interfaces in the future for new things, while keeping your code clean and easy to understand.
- and, most importantly, you will know that your modules will actually declare that they are loaded and/or ready instead of relying on black magic to do it for you.
- 你有一个一致的命名空间供模块居住
- 你有一个一致的接口,它允许任何模块知道如何注册自己
- 您可以在未来轻松扩展模块或注册表接口以获取新事物,同时保持代码干净且易于理解。
- 而且,最重要的是,您会知道您的模块实际上会声明它们已加载和/或准备就绪,而不是依靠黑魔法来为您完成。