我已经知道这个问题有一个答案,但我想提供一个更现实的解决方案,我相信你的问题是。如果我昨天有更多的时间发表我的评论,我会发布这个。对不起,我没有。
这听起来像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.");
}
}
}
?>
现在,在每个模块中,您需要在文件加载时调用该寄存器函数。有几种方法可以做到这一点。首先是在你的模块的名字空间一些代码,类似典型proceedural代码加载运行:
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);
}
}
);
这样做将是定义模块的接口与特定功能时,模块初始化注册的另一种可能的方式。但是,这意味着模块需要首先加载,并且可能会根据您的需求导致它自己的问题。
这样做后:
- 你有一个一致的命名空间模块住在
- 你有一个一致的接口,它允许任何模块知道如何注册自己
- 您可以轻松地扩展模块或注册表接口,用于新事物,同时保持代码清洁且易于理解。
- 和最重要的是,你会知道你的模块会实际声明他们已经加载和/或准备好,而不是依靠黑魔法来为你做。
总之,答案是否定的。有没有这样做的PHP方式。坚持class_exists或is_callable。 – 2011-03-07 23:46:19
@Kevin Peno,讨厌这么说,但正如你在下面看到的,有一种方法可以获得加载的名称空间。 – DonSeba 2011-03-08 07:44:00
对不起,但我直接用PHP说话。和in一样,一个函数检查一个名字空间是否被声明/正在使用。对不起,如果我不够清楚。 – 2011-03-08 17:15:01