我知道这个问题已经有了答案,但我想为我认为您的问题提供一个更现实的解决方案。如果我昨天发表评论时有更多时间,我会发布这个。对不起,我没有。
听起来 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 );
}
}
);
另一种可能的方法是为具有特定功能的模块定义一个接口,以便在模块初始化时进行注册。但是,这意味着需要先加载模块,并且可能会根据您的需要导致它自己的问题。
这样做之后:
- 您有一个一致的命名空间供模块使用
- 你有一个一致的接口,它允许任何模块知道如何注册自己
- 您可以在未来轻松扩展模块或注册表接口以适应新事物,同时保持代码简洁易懂。
- 而且,最重要的是,您将知道您的模块实际上会声明它们已加载和/或准备就绪,而不是依靠黑魔法为您完成。