检索 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;
}
在 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;
}