ZendFramework 2 - удаление InputFilter вызывает неправильное поведение в пользовательском фильтре
У меня есть форма регистрации User\UserForm, которая содержит набор полей User \ UserFieldset. В User \ UserFieldset я поместил поле с именем "passwordVerify", которое должно совпадать с другим полем в наборе полей с именем "password". Это отлично работает.
Однако, если администратор хочет изменить учетную запись пользователя в Admin \ UserForm, которая также содержит User \ UserFieldset, поле "passwordVerify" в fieldset User \ UserFieldset должно быть удалено. Поэтому я вызываю следующее в Admin \ UserForm:
$this->get('user')->remove('passwordVerify');
$this->getInputFilter()->get('user')->remove('passwordVerify')
Как и ожидалось, в форме теперь отсутствует поле "passwordVerify".
Если я сохраню форму после редактирования какого-либо материала, мой пользовательский фильтр "PasswordFilter" больше не сможет извлечь связанный объект из набора полей ($this->getOption('object');
возвращает объект User), но все свойства связанного объекта обнуляются. Если я использую Admin \ UserForm без удаления полей "passwordVerify" и "passwordVerify" -inputfilter, все работает нормально, и связанный объект передается в "PasswordFilter" с заполненными свойствами (в отношении значений, вставленных пользователем в Admin\UserForm). Линия, которая ломает все $this->getInputFilter()->get('user')->remove('passwordVerify')
, Таким образом, это приводит к моему предположению, что, удаляя входной фильтр, гидратированный объект каким-то образом обнуляется / очищается. Ниже приведены некоторые выдержки из моего кода, при необходимости я могу предоставить больше информации о фабриках и т. Д.
Admin \ UserForm:
class UserForm extends Form
{
/**
* @var EntityManager
*/
protected $entityManager = null;
/**
* @var Translator
*/
protected $translator = null;
public function __construct(EntityManager $entityManager, Translator $translator)
{
$this->entityManager = $entityManager;
$this->translator = $translator;
parent::__construct("userForm");
$this->setHydrator(new DoctrineHydrator($entityManager));
}
public function init()
{
// Adding UserFieldset
$this->add(array(
'name' => 'user',
'type' => \User\Form\UserFieldset::class,
'options' => array(
'use_as_base_fieldset' => true,
),
));
$this->get('user')->remove('passwordVerify');
$this->getInputFilter()->get('user')->remove('passwordVerify');
$this->add(array(
'type' => 'Zend\Form\Element\Csrf',
'name' => 'csrf',
));
$this->add(array(
'type' => 'submit',
'name' => 'submit',
'options' => array(
'label' => $this->translator->translate('Btn.submit.user', 'Form')
),
));
}
}
Пользователь \ UserFieldset:
class UserFieldset extends Fieldset implements InputFilterProviderInterface
{
/**
* @var EntityManager
*/
protected $entityManager = null;
/**
* @var Translator
*/
protected $translator = null;
public function __construct(EntityManager $entityManager, Translator $translator)
{
$this->entityManager = $entityManager;
$this->translator = $translator;
parent::__construct("userFieldset");
$this->setHydrator(new DoctrineHydrator($entityManager))->setObject(new User());
}
public function init()
{
$this->add(array(
'type' => 'text',
'name' => 'firstName',
'options' => array(
'label' => $this->translator->translate('label.firstName', 'Form'),
'label_attributes' => array(
'class' => 'col-sm-3',
),
'column-size' => 'sm-5',
),
'attributes' => array(
'id' => 'firstName',
),
));
/* ... */
$this->add(array(
'type' => 'text',
'name' => 'password',
'options' => array(
'label' => $this->translator->translate('label.password', 'Form'),
'label_attributes' => array(
'class' => 'col-sm-3',
),
'column-size' => 'sm-5',
),
'attributes' => array(
'id' => 'password',
),
));
$this->add(array(
'type' => 'password',
'name' => 'passwordVerify',
'options' => array(
'label_attributes' => array(
'class' => 'col-sm-3 control-label'
),
'label' => $this->translator->translate('label.verifyPassword', 'Form'),
'column-size' => 'sm-8',
),
'attributes' => array(
'class' => 'form-control',
'id' => 'password'),
));
/* ... */
// Adding AddressFieldset
$this->add(array(
'name' => 'address',
'type' => \User\Form\AddressFieldset::class,
));
/* ... */
$this->add(array(
'type' => 'datetime',
'name' => 'created',
'options' => array(
'label' => $this->translator->translate('label.created', 'Form'),
'format' => 'd.m.Y H:i',
'label_attributes' => array(
'class' => 'col-sm-3',
),
'column-size' => 'sm-5',
),
'attributes' => array(
'id' => 'created',
),
));
}
public function getInputFilterSpecification()
{
return array(
'firstName' => array(
'required' => true,
'filters' => array(
array('name' => 'StringTrim'),
array('name' => 'StripTags'),
),
'validators' => array(),
),
/* ... */
'password' => array(
'required' => true,
'filters' => array(
array('name' => 'StringTrim'),
array('name' => 'StripTags'),
[
'name' => PasswordFilter::class,
'options' => [
'object' => $this->getObject(),
'field' => 'password'
]
]
),
'validators' => array(),
),
'passwordVerify' => array(
'required' => true,
'filters' => [
[
'name' => PasswordFilter::class,
'options' => [
'object' => $this->getObject(),
'field' => 'password'
]
]
],
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'min' => 6
)
),
array(
'name' => 'Identical',
'options' => array(
'token' => 'password'
)
)
)
),
/* ... */
'created' => array(
'required' => false,
'filters' => array(
array('name' => 'StringTrim'),
),
'validators' => array(
array(
'name' => 'Date',
'options' => array('format' => 'd.m.Y H:i')
),
),
)
);
}
}
PasswordFilter:
class PasswordFilter extends AbstractFilter
{
/** @var EntityManager */
protected $entityManager;
/** @var PasswordInterface */
protected $passwordManager;
/**
* PasswordFilter constructor.
* @param EntityManager $entityManager
* @param PasswordInterface $passwordManager
* @param array $options
*/
public function __construct(EntityManager $entityManager, PasswordInterface $passwordManager, $options = [])
{
$this->entityManager = $entityManager;
$this->passwordManager = $passwordManager;
$this->options = $options;
}
public function filter($value)
{
$object = $this->getOption('object');
$field = $this->getOption('field');
$getter = 'get'.ucfirst($field);
if (!$object || !$field) {
throw new \Exception('Options "object" and "field" are required.');
}
if ($object->getId()) {
$dbObject = $this->entityManager->getRepository(get_class($object))->find($object->getId());
if ($value === $dbObject->{$getter}()) {
return $value;
}
}
// hash password here...
return $this->passwordManager->create($value);
}
private function getOption($option)
{
if (array_key_exists($option, $this->options)) {
return $this->options[$option];
}
return false;
}
}
Есть какие-нибудь подсказки? Должен ли я вызывать удалить входной фильтр "passwordVerify" на ранней стадии процесса создания экземпляра? Я также проверил, чтобы удалить inputFilter и поле после "$this->form->bind($user)" в моем контроллере, что также работает. Почему это не работает, если я удаляю его в Admin \ UserForm, который, по моему мнению, является более чистым способом управления "passwordVerify"?
1 ответ
Если вы позвоните $this->getInputFilter()
, InputProviderInterface::getInputSpecification
метод в вашем UserForm
называется
Если вы еще не прикрепили объект, он не сможет получить его. Но я не понимаю, зачем тебе это нужно. Вы хэшируете пароль, если значение не соответствует значению базы данных, но очевидно, что значение базы данных выглядит как простой текст в качестве входных данных или зачем сравнивать его?
ИМХО, вы просто должны хешировать пароль, независимо от текущего значения в вашей базе данных.
Если вы используете доктрину и пароль не изменится, он все равно не выполнит запрос UPDATE.