Yii2 正在检索控制器/操作的数组

Yii2 正在检索控制器/操作的数组,yii2,Yii2,在Yi2中是否可以检索包含整个应用程序的所有控制器和操作的数组?据我所知,Yi2没有任何内置方法来实现这一点。您只能获取当前控制器及其操作 它的目的是什么?如果您真的需要它,您可以自己编写这样的功能 要获取所有控制器,您应搜索以Conroller结尾的文件。它们可以位于不同的应用位置。例如,在嵌套的文件夹、模块、嵌套的模块等中,因此搜索的位置不止一个 要获取所有操作,应在每个控制器中搜索前缀为操作的所有方法 另外,不要忘记控制器actions()方法中附加的操作。在框架中,它们通常以操作结尾,例

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

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

它的目的是什么?如果您真的需要它,您可以自己编写这样的功能

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

要获取所有操作,应在每个控制器中搜索前缀为操作的所有方法

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

您可能需要排除诸如供应商之类的文件夹


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

我最终得到了:

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;
}

我从安德烈亚斯·亨德伯格的答案开始,并对其进行了微调。我的结局是这样的:

它使用
FileHelper
递归地获取所有文件,这对于从基类扩展控制器非常有用。它还使用
拐点::camel2id
格式化控制器id/动作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;
}

以下示例:巡视所有模块并收集所有模块控制器动作(未测试):


其要点是获取所有控制器的列表,这些控制器的操作用于构建一个数据库表,其中包含每个经过身份验证的角色的控制器/操作,这些角色允许调用或不允许调用。在这种情况下,我可以预定义包含控制器的文件夹。您可以尝试按照我描述的方式执行此操作。但出于这个目的,我认为最好在每个控制器中设置RBAC并通过behaviors()配置AccessControl。这是推荐的标准方法。您可以使用类似于Thx Manquer的方法作为提示。我刚刚发布了我最终得到的解决方案。我想
ActionRequestFile
给我
请求文件
,所以我将其中一行更改为:
$fulllist[substr($controller,0,-4)][]=ltrim(strtolower(内爆('-',预裂('/(?=[A-Z]),$display[1]),'-')听起来很好,但也取决于您如何进一步使用它EndForeach;endif;etc看起来很糟糕这不适用于扩展控制器,例如,如果我使用博客模块并从基本控制器(即从供应商目录)扩展控制器,并且只将我的新自定义操作添加到扩展类中,它将只定义新操作,而不是该类的所有操作。
<?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;
}