Zend Framework 2 通过工厂创建表单。如何根据角色从字段集中删除元素?
Zend Framework 2 Form creation via Factory. How to remove elements from fieldset depending on role?
我正在使用工厂创建一个表单,并通过配置字段集指定表单结构。
但是,具有“admin”角色的用户可以编辑包含实体所有字段的表单,普通用户“client”可以编辑只有几个字段。这就是为什么我必须从控制器中的字段集中删除元素。
$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])
};
}
构造函数的第二个参数可以是任何东西(事实上在 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
}
};
}
上面提供的解决方案很好。如果系统不是很大并且表单中包含的元素很少,则可以对其进行维护。由于系统有点复杂,我决定提供更多的 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;
}
}
这取决于项目结构,希望思路清晰...
我正在使用工厂创建一个表单,并通过配置字段集指定表单结构。
但是,具有“admin”角色的用户可以编辑包含实体所有字段的表单,普通用户“client”可以编辑只有几个字段。这就是为什么我必须从控制器中的字段集中删除元素。
$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])
};
}
构造函数的第二个参数可以是任何东西(事实上在 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
}
};
}
上面提供的解决方案很好。如果系统不是很大并且表单中包含的元素很少,则可以对其进行维护。由于系统有点复杂,我决定提供更多的 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;
}
}
这取决于项目结构,希望思路清晰...