Zend Framework 2通过Factory创建表单。如何根据角色从fieldset中删除元素?

时间:2018-01-09 13:03:41

标签: php zend-framework2

我通过配置Fieldsets来创建使用工厂和指定表单结构的表单。

但是,具有“ admin ”角色的用户可以使用实体的所有字段编辑表单,而常规用户“客户端”只需编辑少数字段。这就是我必须从控制器中的字段集中删除元素的原因。

    $this->form->getBaseFieldset()->remove('name');
    $this->form->getBaseFieldset()->remove('title');
    $this->form->getBaseFieldset()->remove('message');`

是否可以在Fieldset或Form配置中指定必须添加或删除哪个角色元素?

class ZoneDefaultElement extends Fieldset implements InputFilterProviderInterface
{

    public function __construct($name, $entity)
    {
        parent::__construct($name);

        $this->add([
            'name' => 'title',
            'type' => Element\Text::class,
            'attributes' => [
                'class' => 'form-control',
            ],
            'options' => [
                'label' => 'Title',
                'label_attributes' => [
                    'class' => 'col-sm-2 control-label required',
                ],
            ],
        ], ['priority' => 1])
     };
}

2 个答案:

答案 0 :(得分:0)

构造函数的第二个参数可以是任何东西(实际上在Fieldset如果没有给出它是空的array),所以你应该能够传入一个项目数组来使用:

class ZoneDefaultElement extends Fieldset implements InputFilterProviderInterface
{

    public function __construct($name, $options)
    {
        parent::__construct($name);

        $entity = $options['entity'];
        $user = $options['user'];

        // Standard element
        $this->add([
            'name' => 'title',
            'type' => Element\Text::class,
            'attributes' => [
                'class' => 'form-control',
            ],
            'options' => [
                'label' => 'Title',
                'label_attributes' => [
                    'class' => 'col-sm-2 control-label required',
                ],
            ],
        ], ['priority' => 1]);

        if ($user->isAdmin()) {
            // Add "admin-only" elements
        }
    };
}

答案 1 :(得分:0)

上面提供的解决方案非常好。如果系统不是很大并且在表单中包含很少的元素,则可以维护它。由于系统的价格有点复杂,我决定提供更多的OOP解决方案。

class ZoneDefaultElement extends Fieldset implements InputFilterProviderInterface
{
    public function __construct($name, $entity)
    {
        parent::__construct($name);

        $this->add([
            'name' => 'title',
            'options' => [
                'label' => 'Title',                  
            ],
        ], ['priority' => 1, 'access' => ['allow' => ['admin'])
     }
};

拒绝配置将是这样的:

        $this->add([
          'name' => 'message',            
          'options' => [
            'label' => 'Message',              
          ],
        ], ['priority' => 1, 'access' => ['deny' => ['guest'])

我在Fieldset和我的自定义字段集之间添加了一个图层:

class ExtendedFieldset extends Fieldset
{
    public $formMiddleware;

    public function __construct($name = null, $options = array())
    {
        parent::__construct($name);
    }

    public function add($elementOrFieldset, array $flags = [])
    {
        if (array_key_exists('access', $flags)) {
            if(!$this->getFormMiddleware()->filter($flags['access'])){
                return false;
            };
        }
        parent::add($elementOrFieldset, $flags);
    }

    public function setFormMiddleware(FormMiddleware $formMiddleware)
    {
        $this->formMiddleware = $formMiddleware;
    }

    public function getFormMiddleware()
    {
        if (!$this->formMiddleware) {
            throw new \InvalidArgumentException("FormMiddleware not specified");
        }
        return $this->formMiddleware;
    }
}

现在我们必须从这个ExtendedFiedset中扩展,覆盖父add()方法,并为实现过滤器逻辑的中间件设置setter和getter。

class UserFieldset extends ExtendedFieldset implements InputFilterProviderInterface
{
    private $entityManager;

    public function __construct(EntityManager $entity, FormMiddleware $formMiddleware)
    {
        $this->setFormMiddleware($formMiddleware);

        parent::__construct('fieldset');

        $this->add([
            'name' => 'email',
            'type' => Element\Email::class,
            'attributes' => [
                'class' => 'form-control',
                'required'  => 'required',
            ],
            'options' => [
                'label' => 'Email:',
                'label_attributes' => [
                    'class' => 'col-sm-4 control-label required',
                ],
            ],
        ], ['priority' => 1, ['access' => ['deny' => ['guest']]]]);
  }

}

最后是FormMiddleware:

class FormMiddleware
{
    private $authenticationService;

    public function __construct(AuthenticationServiceInterface $service)
    {
        $this->authenticationService = $service;
    }

    private function getUserRole() : string
    {
        $this->getIdentity()->getRole();                
    }

    public function getIdentity()
    {
        $identity = $this->authenticationService->getIdentity();
        return $identity;
    }

    public function filter(array $resource = [])
    {
        $marker = true;
        if(!empty($resource)){

            if(array_key_exists('deny', $resource)){
                if(in_array($this->getUserRole(), $resource['deny'])){
                    $marker = false;
                }else{
                    $marker = true;
                }
            }

            if(array_key_exists('allow', $resource)) {
                if(in_array($this->getUserRole(), $resource['allow'])){
                    $marker = true;
                }else{
                    $marker = false;
                }
            }
        }
        return $marker;
    }
}

这取决于项目结构,我希望一个想法很明确......