3

我想在新的 CakePHP 3.0 中创建一个菜单,我发现使用单元格可能是一个好方法。所以假设我创建了UserMenuCell

class UserMenuCell extends Cell {
    protected $_validCellOptions = [];

    public function display() {
        $menu = [];

        $menu[] = $this ->menu( __('Dashboard'), array( 'controller' => 'Users', 'action' => 'dashboard' ), 'fa-dashboard', [] );

        if( $this -> Auth -> isAuthorized(null, ??? ))
            $menu[] = $this ->menu( __('Barcodes'), array( 'controller' => 'Barcodes', 'action' => 'index' ), 'fa-table', [] );

        $this -> set ( 'menu',  $menu );
    }

    private function menu( $title, $url = [], $icon, $submenu = [] ) {
        return ['title' => $title, 'url' => $url, 'icon' => $icon, 'submenu' => $submenu]; }
}

但是我只想在当前用户被授权管理条形码时才显示条形码项目。我该怎么做?我什至无法访问 $this -> Auth来获取当前用户。

在我的单元格模板中一切正常。我只需要为菜单创建这个嵌套数组。

4

3 回答 3

1

根据 Cookbook 的说法,该会话可从 Cells 中获得。

class UsermenuCell extends Cell
{
    public function display()
    {
        var_dump($this->request->session()->read('Auth'));
    }
}

像这样,您可以在单元格显示功能中读取所需的信息。

于 2017-02-26T16:06:35.230 回答
0

我认为问题解决了:

我可以使控制器具有静态方法,例如_isAuthorized($user, $request)处理授权逻辑的静态公共函数(因此每个控制器只控制自己的权限)。

然后我可以从任何地方打电话,例如PostsController::_isAuthorized($user, ['action' => 'add'])。这应该可以解决我猜的所有问题。另一个好处是传递$this -> Auth -> user()到视图中,因此可以在单元格中使用(通过参数)。

src/Controller/AppController.php

public function beforeFilter(Event $event) {
    $this -> set('user', $this -> Auth -> user());
}

src/View/Cell/MenuCell.php

use App\Controller\PostsController; // Don't forget to use namespace of your Controller

class MenuCell extends Cell {
    public function display($user) {
        $menu = [];
        if (PostsController::_isAuthorized($user, ['action' => 'add'])) // In that method you must handle authorization
            $menu[] = ['title' => 'Add post', 'url' => array('controller' => 'Posts', 'action' => 'add')];
       $this -> set ('menu', $menu); // Handle this in Template/Cell/Menu/display.ctp
    }
}

src/Template/Cell/Menu/display.ctp - 只是为了展示如何渲染菜单

<ul>
    <?php foreach($menu as $item) {
        echo '<li>' . $this -> Html -> link ($item['title'], $item['url']);
    } ?>
</ul>

src/Template/Layout/default.ctp - 在主布局中渲染菜单

<?= $this -> cell('Menu', array($user)) /* This is the user passed from beforeFilter */ ?>

然后你可以玩isAuthorized方法。例如,您可以编辑您的AppController. 总是当CakePHP调用isAuthorized函数时,它会被重定向到YourNameController::_isAuthorized()静态方法(如果存在)。

src/Controller/AppController.php

public function isAuthorized( $user ) {
    $childClass = get_called_class();

    if(method_exists($childClass, '_isAuthorized'))
        return $childClass::_isAuthorized($user, $this -> request);

    return static::_isAuthorized($user, $request);
}

static public function _isAuthorized($user, $request)
{
    if ($user['role'] == 'admin')
        return true;

    return false; // By default deny any unwanted access
}

这是您的控制器的示例。您只能指定静态_isAuthorized($user, $request)方法,因为出于CakePHP默认行为的目的,它将被调用AppController::isAuthorized(参见上面的代码)。

src/Controller/PostController.php

static public function _isAuthorized($user, $request)
{
    $action = ($request instanceof Cake\Network\Request) ? $request -> action : $request['action'];

    if($action == 'add' && $user['role'] == 'CanAddPosts')
        return true;

    return parent::_isAuthorized($user, $request);
}

如您所见,我让 $request 接受一个数组Cake\Network\Request对象。那是因为CakePHPRequest对象调用它,但是当我调用它时,我不需要创建这个对象,因为我的参数很简单(参见MenuCell.php上面的代码)。

当然你现在可以做更复杂的逻辑,比如用户可以有更多的角色,用逗号分隔,你可以分解这个并检查用户是否有in_array的权限。现在,您的权限背后的逻辑是什么,这完全取决于您。每个控制器都可以处理自己的权限管理,而您始终可以通过每个用户和每个页面请求访问这些权限。

于 2014-08-23T21:21:52.880 回答
0

如果你传递会话变量?

<?= $this->cell('userMenu', $this->Session->read('Auth')); ?>
于 2014-08-23T19:40:08.243 回答