2018-08-03 17:03:45 436次浏览 6条回答 4 悬赏 10 金钱

现在需要做RBAC权限管理,但我不想一个 module->controller->action 的添加菜单,想一下循环出全部Module,controller,action|搞了两三天了。。。始终没找到解决办法

补充于 2018-08-03 17:07

现在能获取到 Module 的列表。。。contoller 啥的都没法遍历出来

  • 回答于 2018-08-03 18:10
    Yii::$app->getModule('user')->getControllerPath()
    

    通过获取模块下的控制器文件,来取到所有控制器的名称。

    2 条回复
    回复于 2018-08-03 18:37
    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;
    }
    

    https://stackoverflow.com/questions/27912988/retrieving-array-of-controllers-actions
    这是一个完整的例子。

    回复于 2018-08-04 16:33

    谢谢巡航舰哥!

    , 觉得很赞
  • 回答于 2018-08-08 13:21

    mark一下,这个不错

  • 回答于 2018-10-24 15:43

    如果再用yii2 admin,可以看一下:models\Route中的相关方法,他应该能满足你的需求

    1 条回复
    回复于 2018-10-25 10:25

    具体怎么实现你呢能麻烦写份代码吗?或者具体啥方法?

  • 回答于 2018-10-24 15:53

    ╃巡洋艦㊣给的方法也不错,可以看一下别人实现的思路。但这种方法是从指定的文件夹去获取controller,然后去自动解析。如果放到更改controller文件夹的应用中,就需要修改代码去适应。Yii本身已经给我们提供了很多的方法,使用这些现有的,其适应性更强一些。再就是,yii的Application其实也是继承自Module,是一个特殊的module。

    6 条回复
    回复于 2018-10-25 23:19


    $test = '测试';

    回复于 2018-10-25 23:20
    $test = '测试';
    回复于 2018-10-25 23:22


    Yii::$app->getModule('user')->getControllerPath();

    回复于 2018-10-25 23:23


    Yii::$app->getModule('user')->getControllerPath();

    回复于 2018-10-25 23:26


    Yii::$app->getModule('user')->getControllerPath();

    回复于 2018-10-25 23:30

    `php Yii::$app->getModule('user')->getControllerPath(); `

  • 回答于 2018-10-25 23:31

    ``php
    Yii::$app->getModule('user')->getControllerPath();

    ``

    Yii::$app->getModule('user')->getControllerPath();
    
  • 回答于 2018-10-25 23:37

    Yii admin 可以搜索一下:mdmsoft/yii2-admin
    一个Configs.php,可以在配置文件中自己配置menu表和user表的名称,如下:

    
    namespace mdm\admin\components;
    
    use Yii;
    use yii\caching\Cache;
    use yii\db\Connection;
    use yii\di\Instance;
    use yii\helpers\ArrayHelper;
    use yii\rbac\ManagerInterface;
    
    /**
     * Configs
     * Used to configure some values. To set config you can use [[\yii\base\Application::$params]]
     *
     * 
     * return [
     *
     *     'mdm.admin.configs' => [
     *         'db' => 'customDb',
     *         'menuTable' => '{{%admin_menu}}',
     *         'cache' => [
     *             'class' => 'yii\caching\DbCache',
     *             'db' => ['dsn' => 'sqlite:@runtime/admin-cache.db'],
     *         ],
     *     ]
     * ];
     * 
     *
     * or use [[\Yii::$container]]
     *
     * 
     * Yii::$container->set('mdm\admin\components\Configs',[
     *     'db' => 'customDb',
     *     'menuTable' => 'admin_menu',
     * ]);
     * 
     *
     * @author Misbahul D Munir <misbahuldmunir@gmail.com>
     * @since 1.0
     */
    
    class Configs extends \mdm\admin\BaseObject
    {
        const CACHE_TAG = 'mdm.admin';
    
        /**
         * @var ManagerInterface .
         */
        public $authManager = 'authManager';
    
        /**
         * @var Connection Database connection.
         */
        public $db = 'db';
    
        /**
         * @var Connection Database connection.
         */
        public $userDb = 'db';
    
        /**
         * @var Cache Cache component.
         */
        public $cache = 'cache';
    
        /**
         * @var integer Cache duration. Default to a hour.
         */
        public $cacheDuration = 3600;
    
        /**
         * @var string Menu table name.
         */
        public $menuTable = '{{%menu}}';
    
        /**
         * @var string Menu table name.
         */
        public $userTable = '{{%user}}';
    
        /**
         * @var integer Default status user signup. 10 mean active.
         */
        public $defaultUserStatus = 10;
    
        /**
         * @var boolean If true then AccessControl only check if route are registered.
         */
        public $onlyRegisteredRoute = false;
    
        /**
         * @var boolean If false then AccessControl will check without Rule.
         */
        public $strict = true;
    
        /**
         * @var array
         */
        public $options;
    
        /**
         * @var array|false
         */
        public $advanced;
    
        /**
         * @var self Instance of self
         */
        private static $_instance;
        private static $_classes = [
            'db' => 'yii\db\Connection',
            'userDb' => 'yii\db\Connection',
            'cache' => 'yii\caching\Cache',
            'authManager' => 'yii\rbac\ManagerInterface',
        ];
    
        /**
         * @inheritdoc
         */
        public function init()
        {
            foreach (self::$_classes as $key => $class) {
                try {
                    $this->{$key} = empty($this->{$key}) ? null : Instance::ensure($this->{$key}, $class);
                } catch (\Exception $exc) {
                    $this->{$key} = null;
                    Yii::error($exc->getMessage());
                }
            }
        }
    
        /**
         * Create instance of self
         * @return static
         */
        public static function instance()
        {
            if (self::$_instance === null) {
                $type = ArrayHelper::getValue(Yii::$app->params, 'mdm.admin.configs', []);
                if (is_array($type) && !isset($type['class'])) {
                    $type['class'] = static::className();
                }
    
                return self::$_instance = Yii::createObject($type);
            }
    
            return self::$_instance;
        }
    
        public static function __callStatic($name, $arguments)
        {
            $instance = static::instance();
            if ($instance->hasProperty($name)) {
                return $instance->$name;
            } else {
                if (count($arguments)) {
                    $instance->options[$name] = reset($arguments);
                } else {
                    return array_key_exists($name, $instance->options) ? $instance->options[$name] : null;
                }
            }
        }
    
        /**
         * @return Connection
         */
        public static function db()
        {
            return static::instance()->db;
        }
    
        /**
         * @return Connection
         */
        public static function userDb()
        {
            return static::instance()->userDb;
        }
    
        /**
         * @return Cache
         */
        public static function cache()
        {
            return static::instance()->cache;
        }
    
        /**
         * @return ManagerInterface
         */
        public static function authManager()
        {
            return static::instance()->authManager;
        }
        /**
         * @return integer
         */
        public static function cacheDuration()
        {
            return static::instance()->cacheDuration;
        }
    
        /**
         * @return string
         */
        public static function menuTable()
        {
            return static::instance()->menuTable;
        }
    
        /**
         * @return string
         */
        public static function userTable()
        {
            return static::instance()->userTable;
        }
    
        /**
         * @return string
         */
        public static function defaultUserStatus()
        {
            return static::instance()->defaultUserStatus;
        }
    
        /**
         * @return boolean
         */
        public static function onlyRegisteredRoute()
        {
            return static::instance()->onlyRegisteredRoute;
        }
    
        /**
         * @return boolean
         */
        public static function strict()
        {
            return static::instance()->strict;
        }
    }
    

    Route模型代码中,与你的问题有关的是几个function如下:

    • public function getAppRoutes($module = null)
    • protected function getRouteRecursive($module, &$result)
    • protected function getControllerFiles($module, $namespace, $prefix, &$result)
    • protected function getControllerActions($type, $id, $module, &$result)
    • protected function getActionRoutes($controller, &$result)
      可以重点看一下,具体代码如下:
    
    
    namespace mdm\admin\models;
    
    use Exception;
    use mdm\admin\components\Configs;
    use mdm\admin\components\Helper;
    use mdm\admin\components\RouteRule;
    use Yii;
    use yii\caching\TagDependency;
    use yii\helpers\VarDumper;
    
    /**
     * Description of Route
     *
     * @author Misbahul D Munir <misbahuldmunir@gmail.com>
     * @since 1.0
     */
    class Route extends \mdm\admin\BaseObject
    {
        const CACHE_TAG = 'mdm.admin.route';
    
        const PREFIX_ADVANCED = '@';
        const PREFIX_BASIC = '/';
    
        private $_routePrefix;
    
        /**
         * Assign or remove items
         * @param array $routes
         * @return array
         */
        public function addNew($routes)
        {
            $manager = Configs::authManager();
            foreach ($routes as $route) {
                try {
                    $r = explode('&', $route);
                    $item = $manager->createPermission($this->getPermissionName($route));
                    if (count($r) > 1) {
                        $action = '/' . trim($r[0], '/');
                        if (($itemAction = $manager->getPermission($action)) === null) {
                            $itemAction = $manager->createPermission($action);
                            $manager->add($itemAction);
                        }
                        unset($r[0]);
                        foreach ($r as $part) {
                            $part = explode('=', $part);
                            $item->data['params'][$part[0]] = isset($part[1]) ? $part[1] : '';
                        }
                        $this->setDefaultRule();
                        $item->ruleName = RouteRule::RULE_NAME;
                        $manager->add($item);
                        $manager->addChild($item, $itemAction);
                    } else {
                        $manager->add($item);
                    }
                } catch (Exception $exc) {
                    Yii::error($exc->getMessage(), __METHOD__);
                }
            }
            Helper::invalidate();
        }
    
        /**
         * Assign or remove items
         * @param array $routes
         * @return array
         */
        public function remove($routes)
        {
            $manager = Configs::authManager();
            foreach ($routes as $route) {
                try {
                    $item = $manager->createPermission($this->getPermissionName($route));
                    $manager->remove($item);
                } catch (Exception $exc) {
                    Yii::error($exc->getMessage(), __METHOD__);
                }
            }
            Helper::invalidate();
        }
    
        /**
         * Returns route prefix depending on the configuration.
         * @return string Route prefix
         */
        public function getRoutePrefix()
        {
            if (!$this->_routePrefix) {
                $this->_routePrefix = Configs::instance()->advanced ? self::PREFIX_ADVANCED : self::PREFIX_BASIC;
            }
            return $this->_routePrefix;
        }
    
        /**
         * Returns the correct permission name depending on the configuration.
         * @param  string $route Route
         * @return string        Permission name
         */
        public function getPermissionName($route)
        {
            if (self::PREFIX_BASIC == $this->routePrefix) {
                return self::PREFIX_BASIC . trim($route, self::PREFIX_BASIC);
            } else {
                return self::PREFIX_ADVANCED . ltrim(trim($route, self::PREFIX_BASIC), self::PREFIX_ADVANCED);
            }
        }
    
        /**
         * Get available and assigned routes
         * @return array
         */
        public function getRoutes()
        {
            $manager = Configs::authManager();
            // Get advanced configuration
            $advanced = Configs::instance()->advanced;
            if ($advanced) {
                // Use advanced route scheme.
                // Set advanced route prefix.
                $this->_routePrefix = self::PREFIX_ADVANCED;
                // Create empty routes array.
                $routes = [];
                // Save original app.
                $yiiApp = Yii::$app;
                // Step through each configured application
                foreach ($advanced as $id => $configPaths) {
                    // Force correct id string.
                    $id = $this->routePrefix . ltrim(trim($id), $this->routePrefix);
                    // Create empty config array.
                    $config = [];
                    // Assemble configuration for current app.
                    foreach ($configPaths as $configPath) {
                        // Merge every new configuration with the old config array.
                        $config = yii\helpers\ArrayHelper::merge($config, require (Yii::getAlias($configPath)));
                    }
                    // Create new app using the config array.
                    unset($config['bootstrap']);
                    $app = new yii\web\Application($config);
                    // Get all the routes of the newly created app.
                    $r = $this->getAppRoutes($app);
                    // Dump new app
                    unset($app);
                    // Prepend the app id to all routes.
                    foreach ($r as $route) {
                        $routes[$id . $route] = $id . $route;
                    }
                }
                // Switch back to original app.
                Yii::$app = $yiiApp;
                unset($yiiApp);
            } else {
                // Use basic route scheme.
                // Set basic route prefix
                $this->_routePrefix = self::PREFIX_BASIC;
                // Get basic app routes.
                $routes = $this->getAppRoutes();
            }
            $exists = [];
            foreach (array_keys($manager->getPermissions()) as $name) {
                if ($name[0] !== $this->routePrefix) {
                    continue;
                }
                $exists[] = $name;
                unset($routes[$name]);
            }
            return [
                'available' => array_keys($routes),
                'assigned' => $exists,
            ];
        }
    
        /**
         * Get list of application routes
         * @return array
         */
        public function getAppRoutes($module = null)
        {
            if ($module === null) {
                $module = Yii::$app;
            } elseif (is_string($module)) {
                $module = Yii::$app->getModule($module);
            }
            $key = [__METHOD__, Yii::$app->id, $module->getUniqueId()];
            $cache = Configs::instance()->cache;
            if ($cache === null || ($result = $cache->get($key)) === false) {
                $result = [];
                $this->getRouteRecursive($module, $result);
                if ($cache !== null) {
                    $cache->set($key, $result, Configs::instance()->cacheDuration, new TagDependency([
                        'tags' => self::CACHE_TAG,
                    ]));
                }
            }
    
            return $result;
        }
    
        /**
         * Get route(s) recursive
         * @param \yii\base\Module $module
         * @param array $result
         */
        protected function getRouteRecursive($module, &$result)
        {
            $token = "Get Route of '" . get_class($module) . "' with id '" . $module->uniqueId . "'";
            Yii::beginProfile($token, __METHOD__);
            try {
                foreach ($module->getModules() as $id => $child) {
                    if (($child = $module->getModule($id)) !== null) {
                        $this->getRouteRecursive($child, $result);
                    }
                }
    
                foreach ($module->controllerMap as $id => $type) {
                    $this->getControllerActions($type, $id, $module, $result);
                }
    
                $namespace = trim($module->controllerNamespace, '\\') . '\\';
                $this->getControllerFiles($module, $namespace, '', $result);
                $all = '/' . ltrim($module->uniqueId . '/*', '/');
                $result[$all] = $all;
            } catch (\Exception $exc) {
                Yii::error($exc->getMessage(), __METHOD__);
            }
            Yii::endProfile($token, __METHOD__);
        }
    
        /**
         * Get list controller under module
         * @param \yii\base\Module $module
         * @param string $namespace
         * @param string $prefix
         * @param mixed $result
         * @return mixed
         */
        protected function getControllerFiles($module, $namespace, $prefix, &$result)
        {
            $path = Yii::getAlias('@' . str_replace('\\', '/', $namespace), false);
            $token = "Get controllers from '$path'";
            Yii::beginProfile($token, __METHOD__);
            try {
                if (!is_dir($path)) {
                    return;
                }
                foreach (scandir($path) as $file) {
                    if ($file == '.' || $file == '..') {
                        continue;
                    }
                    if (is_dir($path . '/' . $file) && preg_match('%^[a-z0-9_/]+$%i', $file . '/')) {
                        $this->getControllerFiles($module, $namespace . $file . '\\', $prefix . $file . '/', $result);
                    } elseif (strcmp(substr($file, -14), 'Controller.php') === 0) {
                        $baseName = substr(basename($file), 0, -14);
                        $name = strtolower(preg_replace('/(?<![A-Z])[A-Z]/', ' \0', $baseName));
                        $id = ltrim(str_replace(' ', '-', $name), '-');
                        $className = $namespace . $baseName . 'Controller';
                        if (strpos($className, '-') === false && class_exists($className) && is_subclass_of($className, 'yii\base\Controller')) {
                            $this->getControllerActions($className, $prefix . $id, $module, $result);
                        }
                    }
                }
            } catch (\Exception $exc) {
                Yii::error($exc->getMessage(), __METHOD__);
            }
            Yii::endProfile($token, __METHOD__);
        }
    
        /**
         * Get list action of controller
         * @param mixed $type
         * @param string $id
         * @param \yii\base\Module $module
         * @param string $result
         */
        protected function getControllerActions($type, $id, $module, &$result)
        {
            $token = "Create controller with cofig=" . VarDumper::dumpAsString($type) . " and id='$id'";
            Yii::beginProfile($token, __METHOD__);
            try {
                /* @var $controller \yii\base\Controller */
                $controller = Yii::createObject($type, [$id, $module]);
                $this->getActionRoutes($controller, $result);
                $all = "/{$controller->uniqueId}/*";
                $result[$all] = $all;
            } catch (\Exception $exc) {
                Yii::error($exc->getMessage(), __METHOD__);
            }
            Yii::endProfile($token, __METHOD__);
        }
    
        /**
         * Get route of action
         * @param \yii\base\Controller $controller
         * @param array $result all controller action.
         */
        protected function getActionRoutes($controller, &$result)
        {
            $token = "Get actions of controller '" . $controller->uniqueId . "'";
            Yii::beginProfile($token, __METHOD__);
            try {
                $prefix = '/' . $controller->uniqueId . '/';
                foreach ($controller->actions() as $id => $value) {
                    $result[$prefix . $id] = $prefix . $id;
                }
                $class = new \ReflectionClass($controller);
                foreach ($class->getMethods() as $method) {
                    $name = $method->getName();
                    if ($method->isPublic() && !$method->isStatic() && strpos($name, 'action') === 0 && $name !== 'actions') {
                        $name = strtolower(preg_replace('/(?<![A-Z])[A-Z]/', ' \0', substr($name, 6)));
                        $id = $prefix . ltrim(str_replace(' ', '-', $name), '-');
                        $result[$id] = $id;
                    }
                }
            } catch (\Exception $exc) {
                Yii::error($exc->getMessage(), __METHOD__);
            }
            Yii::endProfile($token, __METHOD__);
        }
    
        /**
         * Ivalidate cache
         */
        public static function invalidate()
        {
            if (Configs::cache() !== null) {
                TagDependency::invalidate(Configs::cache(), self::CACHE_TAG);
            }
        }
    
        /**
         * Set default rule of parameterize route.
         */
        protected function setDefaultRule()
        {
            if (Configs::authManager()->getRule(RouteRule::RULE_NAME) === null) {
                Configs::authManager()->add(new RouteRule());
            }
        }
    }
    
    
您需要登录后才可以回答。登录 | 立即注册
wpj130
职场新人

wpj130

注册时间:2018-07-03
最后登录:2018-11-26
在线时长:2小时26分
粉丝1
金钱45
威望0
积分65

热门问题