0

我有一個註冊表單User \ UserForm,其中包含一個字段User User \ UserFieldset。在User \ UserFieldset中,我放置了一個名爲「passwordVerify」的字段,該字段應該與名爲「password」的字段集中的另一個字段相同。 這工作正常。ZendFramework 2 - 刪除InputFilter導致自定義過濾器中的行爲不當

但是,如果管理員想要修改Admin \ UserForm(其中還包含User \ UserFieldset)中的用戶帳戶,則應刪除字段集User \ UserFieldset中的字段「passwordVerify」。因此,我呼籲管理\用戶窗體中的以下內容:

$this->get('user')->remove('passwordVerify'); 
$this->getInputFilter()->get('user')->remove('passwordVerify') 

正如預期的那樣,形式現在缺乏的領域「passwordVerify」。

如果我在編輯一些東西后保存表單,我的自定義篩選器「PasswordFilter」不能再檢索字段集的綁定對象($this->getOption('object');返回一個用戶對象) - 但綁定對象的所有屬性都是零。如果我在不刪除「passwordVerify」字段和「passwordVerify」的情況下使用Admin \ UserForm,則輸入過濾器一切正常,並且綁定的對象被傳遞給帶有填充屬性的「PasswordFilter」(關於用戶在Admin \用戶窗體)。打破一切的線是$this->getInputFilter()->get('user')->remove('passwordVerify')。因此,這導致了我的假設,即通過移除輸入過濾器,水合物體不知何故被清空/清空。下面是我的我的代碼的一些摘錄,如果需要,我可以提供有關工廠的更多信息,等

管理\用戶窗體:

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」的remove inputfilter? 我也測試過在我的控制器中刪除「$ this-> form-> bind($ user)」之後的inputFilter和field,這也是有效的。爲什麼它不起作用,那麼如果我在Admin \ UserForm中刪除它,這在我看來是管理「passwordVerify」-stuff的更簡潔的方式?

回答

0

如果您致電$this->getInputFilter(),則會調用UserForm中的InputProviderInterface::getInputSpecification方法。

如果您尚未附加對象,則無法檢索它。 但我不明白爲什麼你甚至會需要。如果該值與數據庫值不匹配,那麼您會對密碼進行哈希處理,但顯然數據庫值似乎是純文本作爲輸入,或者您爲什麼要比較它?

恕我直言,你只是應該散列密碼,不管你的數據庫中的當前值是什麼。

如果你使用的教義和密碼不會改變,它不會執行UPDATE查詢。

+0

如果我們要編輯註冊用戶,他的密碼已經被散列。如果我們不修改密碼,那麼「密碼」字段會被散列的密碼popultated,並且不應該是「雙」散列。但是如果f。即應該通過管理員表單從頭開始創建用戶帳戶,我們需要散列給定的密碼,該密碼將以明文形式輸入。因此,我將輸入的密碼與數據庫值進行比較,以瞭解是否需要再次散列密碼(如果值匹配,密碼未更改,如果不存在,或者傳遞了新密碼,則會被散列)。 – mfuesslin