在 Yii2 中获取子模块的所有父模块列表,反之亦然

Get list of all parent modules of a child module and vice versa in Yii2

我的模块层次结构如下

yii/web/Application -> frontend\modules\mangomod\MangomodModule -> frontend\modules\mangomod\modules\lemonmod\Lemonmod -> frontend\modules\mangomod\modules\lemonmod\modules\grapemod\Grapemod

自举模块是:

yii\debug\Moduleyii\gii\Module

现在在 Grapemod 模块的 DefaultController 中,我需要知道它的所有父模块。怎么样?

现在在 Lemonmod 模块的 DefaultController 中,我需要知道它的所有子模块。怎么样?

我试过 yii\base\Application::$loadedModules 但它也提供了我不想要的自举模块,例如 giidebug

这是 yii\base\Application::$loadedModules 的结果:

[0] => yii\web\Application
[1] => frontend\modules\mangomod\MangomodModule
[2] => yii\debug\Module
[3] => yii\gii\Module
[4] => frontend\modules\mangomod\modules\lemonmod\Lemonmod
[5] => frontend\modules\mangomod\modules\lemonmod\modules\grapemod\Grapemod

更新 lemonmod 获得了它的兄弟模块

frontend\modules\mangomod\modules\lemonmod2\Lemonmod2Module

grapemod 获得了它的兄弟模块

frontend\modules\mangomod\modules\lemonmod\modules\grapemod2\Grapemod2Module

要获取控制器的所有祖先模块,您可以使用 Controller::getModules() 方法:

$modules = $controller->getModules();

Returns all ancestor modules of this controller.

The first module in the array is the outermost one (i.e., the application instance), while the last is the innermost one.

https://www.yiiframework.com/doc/api/2.0/yii-base-controller#getModules()-detail


要获取子模块列表,您可以使用此方法的 Module::getModules(). However it will return module config instead of module instance for not loaded modules - it is documented in $loadedOnly 参数:

Whether to return the loaded sub-modules only. If this is set false, then all sub-modules registered in this module will be returned, whether they are loaded or not. Loaded modules will be returned as objects, while unloaded modules as configuration arrays.

如果你想获取所有模块的实例,你应该手动实例化非加载模块:

$modules = [];
foreach ($module->getModules() as $id => $child) {
    if (!$child instanceof Module) {
        $child = $module->getModule($id);
    }
    $modules[] = $child;
}

此外,这将 return 仅引导子模块 - 要获取所有后代,您需要遍历模块树:

/**
 * Return all descendants of given module.
 * 
 * @param Module $module
 * @return Module[]
 */
$traverse = function (Module $module) use (&$traverse) {
    $modules = [];
    foreach ($module->getModules() as $id => $child) {
        if (!$child instanceof Module) {
            $child = $module->getModule($id);
        }
        $modules[] = $child;
        $modules = array_merge($modules, $traverse($child));
    }

    return $modules;
};
$modules = $traverse($module);