检索 Controllers/Actions 的数组

Retrieving array of Controllers/Actions

在 Yii2 中是否可以检索包含整个应用程序的所有控制器和操作的数组?

据我所知,Yii 2 没有任何内置方法来实现这一点。只能获取当前控制器及其动作。

这样做的目的是什么?如果你真的需要这个你可以自己写这样的功能。

要获取所有控制器,您应该搜索以 Conroller 结尾的文件。它们可以位于不同的应用程序位置。例如在嵌套文件夹、模块、嵌套模块等中。所以搜索的地方不止一个。

要获得所有操作,您应该在每个控制器中搜索以 action 为前缀的所有方法。

另外不要忘记控制器 actions() 方法中的附加操作。在框架中,它们通常以 Action 结尾,例如查看 rest 动作。但是没有人强迫你这样命名,所以有可能一些外部动作可以有不同的命名约定(例如,如果你在团队中工作并且不遵循这个约定)。

您可能需要排除 vendor.

等文件夹

所以这不是一项微不足道的任务,但可能存在一些不准确之处。我只是不明白那有什么意义。

我终于得到了:

protected function actionGetcontrollersandactions()
{
    $controllerlist = [];
    if ($handle = opendir('../controllers')) {
        while (false !== ($file = readdir($handle))) {
            if ($file != "." && $file != ".." && substr($file, strrpos($file, '.') - 10) == 'Controller.php') {
                $controllerlist[] = $file;
            }
        }
        closedir($handle);
    }
    asort($controllerlist);
    $fulllist = [];
    foreach ($controllerlist as $controller):
        $handle = fopen('../controllers/' . $controller, "r");
        if ($handle) {
            while (($line = fgets($handle)) !== false) {
                if (preg_match('/public function action(.*?)\(/', $line, $display)):
                    if (strlen($display[1]) > 2):
                        $fulllist[substr($controller, 0, -4)][] = strtolower($display[1]);
                    endif;
                endif;
            }
        }
        fclose($handle);
    endforeach;
    return $fulllist;
}

我从 Andreas Hinderberger 的回答开始,然后对其进行了微调。我最终得到了这样的结果:

它使用 FileHelper 递归地获取所有文件,这在您从基础 类 扩展控制器时很有用。它还使用 Inflector::camel2id 格式化 controller-id/action-id,以便它们匹配您的路线。

public function getAllControllerActions()
{
    $controllers = \yii\helpers\FileHelper::findFiles(Yii::getAlias('@app/controllers'), ['recursive' => true]);
    $actions = [];
    foreach ($controllers as $controller) {
        $contents = file_get_contents($controller);
        $controllerId = Inflector::camel2id(substr(basename($controller), 0, -14));
        preg_match_all('/public function action(\w+?)\(/', $contents, $result);
        foreach ($result[1] as $action) {
            $actionId = Inflector::camel2id($action);
            $route = $controllerId . '/' . $actionId;
            $actions[$route] = $route;
        }
    }
    asort($actions);
    return $actions;
}

按照示例遍历所有模块并收集所有模块控制器操作(未测试):

<?php

$controllerDirs = [];
$controllerDirs[] = \Yii::getAlias('@app/controllers');
if ($commonControllerDir = \Yii::getAlias('@common/controllers', false)) {
    $controllerDirs['common'] = $commonControllerDir;
}
foreach (\Yii::$app->modules as $moduleId => $module) {
    /*
     * get module base path
     */
    if (method_exists($module, 'getBasePath')) {
        $basePath = $module->getBasePath();
    } else {
        $reflector = new \ReflectionClass($module['class']);
        $basePath = StringHelper::dirname($reflector->getFileName());
    }
    $basePath .= '/controllers';
    $controllerDirs[$moduleId] = $basePath;
}

$actions = [];
foreach ($controllerDirs as $moduleId => $cDir) {
    $actions[$moduleId][$cDir] = actionGetcontrollersandactions($cDir);
}
print_r($actions);


function actionGetcontrollersandactions($controllerDir) {
    $controllerlist = [];
    if ($handle = opendir($controllerDir)) {
        while (false !== ($file = readdir($handle))) {
            if ($file != "." && $file != ".." && substr($file, strrpos($file, '.') - 10) == 'Controller.php') {
                $controllerlist[] = $file;
            }
        }
        closedir($handle);
    }
    asort($controllerlist);
    $fulllist = [];
    foreach ($controllerlist as $controller):
        $handle = fopen($controllerDir . '/' . $controller, "r");
        if ($handle) {
            while (($line = fgets($handle)) !== false) {
                if (preg_match('/public function action(.*?)\(/', $line, $display)):
                    if (strlen($display[1]) > 2):
                        $fulllist[substr($controller, 0, -4)][] = strtolower($display[1]);
                    endif;
                endif;
            }
        }
        fclose($handle);
    endforeach;
    return $fulllist;
}