2015-03-02 101 views
0

我有一個帶表單集合元素的ZF2表單。我有教條2實體。我將這個實體綁定到表單上。 這裏是我的代碼:ZF2表單集合和教條2

$form->bind($entity); // $entity->roles is not empty. It has two elements 
$form->setData($someData); // $someData['roles'] is empty array 
if ($form->isValid()) { 
    $form->get('roles')->getCount(); // 2(!) it is not empty! 
    saveToDb($entity); 
} 
return $form; 

Form集合的名稱是 「角色」。在將數據設置爲表單之前,您可以看到我綁定了實體。 當用戶想要更新實體時,實體已經有了值。例如,表單集合中已經有兩個值。例如,用戶想要清除角色,$ someData數組具有空角色。問題是$ form-> setData不清除角色集合。如何清除此集合?如果你看看Collection :: populateValues()方法,你會發現如果數據是空的,它什麼也不做。

回答

1

這似乎是與此相關的錯誤:https://github.com/zendframework/zf2/issues/4492

和可能的臨時解決方案可以是:

if (empty($someData['roles'])) { 
    $entity->setRoles(array()); 
} 
$form->bind($entity); 
$form->setData($someData); 
if ($form->isValid()) { 
    saveToDb($entity); 
} 
return $form; 
0

我有兩個實體(角色&權限),一個ID我的角色實體存在,名稱和ArrayCollections的權限實體:

object(Authorization\Entity\Role)#525 (3) { 
    ["id":protected] => 1 
    ["name":protected] => string(7) "admin" 
    ["permissions":protected] => object(Doctrine\Common\Collections\ArrayCollection)#524 (1) { 
    ["_elements":"Doctrine\Common\Collections\ArrayCollection":private] => array(4) { 
     [1] => object(Authorization\Entity\Permission)#527 (2) { 
     ["id":protected] => int(1) 
     ["name":protected] => "createUser" 
     } 
     [2] => object(Authorization\Entity\Permission)#529 (2) { 
     ["id":protected] => int(2) 
     ["name":protected] => "updateUser" 
     } 
     [3] => object(Authorization\Entity\Permission)#526 (2) { 
     ["id":protected] => int(3) 
     ["name":protected] => "createRole" 
     } 
     [4] => object(Authorization\Entity\Permission)#528 (2) { 
     ["id":protected] => int(4) 
     ["name":protected] => "updateRole" 
     } 
    } 
    } 
} 

要更新/清除權限,我將數據從窗體發送到我的Rol eDao:

public function update(RoleViewObject $roleVO) { 
     // Find VO by using the getId() function to update 
     // the right VO object 
     $role = $this->getRoleById($roleVO->getId()); 

     // Delete all permissions from VO <--- I think this is what you need 
     $role->getPermissions()->clear(); 

     // Add updated permissions to VO 
     foreach($roleVO->getPermissions() as $permissionId => &$permissionVO) { 
      $permissionName = $permissionVO->getName(); 
      if(empty($permissionName)) { 
       $role->getPermissions()->set($permissionVO->getId(), $this->entityManager->getReference('Authorization\Entity\Permission', $permissionVO->getId())); 
      } 
     } 

     $this->entityManager->persist($role); 
     $this->entityManager->flush(); 
    } 
0

實際問題是,Zend的形式不與尚未發送的值理會,並在排空收集的情況下,您只需將不會發送任何數據,這是爲什麼表格忽略集合,導致表單和/或其字段集不告訴他們的水化器對集合進行任何更改。

最終,您可以責怪this函數,該函數刪除從傳遞給「setData」的數組中未表示的表單中提取的過濾數據。

我管理通過重寫形式的「使用setData」功能附加地處理所傳遞的數據,以包括空數組爲仍處於字段集集合來解決這個問題,但在數據陣列中未表示:

namespace Module\Form; 

class Form extends \Zend\Form\Form 
{ 
    /** 
    * Fill the passed data array with placeholder arrays for collections 
    * existing in the passed fieldset (and its sub-fieldsets) but not 
    * represented in the data array. 
    * 
    * @param \Zend\Form\FieldsetInterface $fieldset 
    * @param array $data 
    * @return array 
    */ 
    protected static function assertCollectionPlaceholders(\Zend\Form\FieldsetInterface $fieldset, array $data) 
    { 
     foreach ($fieldset as $name => $elementOrFieldset) { 
      if (!$elementOrFieldset instanceof \Zend\Form\FieldsetInterface) { 
       continue; 
      } 

      if (array_key_exists($name, $data) && is_array($data[$name])) { 
       $data[$name] = static::assertCollectionPlaceholders($elementOrFieldset, $data[$name]); 
      } else if ($elementOrFieldset instanceof \Zend\Form\Element\Collection) { 
       $data[$name] = array(); 
      } 
     } 

     return $data; 
    } 

    /** 
    * Set data to validate and/or populate elements 
    * 
    * Typically, also passes data on to the composed input filter. 
    * 
    * @see \Zend\Form\Form 
    * @param array|\ArrayAccess|Traversable $data 
    * @return self 
    * @throws \Zend\Form\Exception\InvalidArgumentException 
    */ 
    public function setData($data) 
    { 
     if ($data instanceof \Traversable) { 
      $data = \Zend\Stdlib\ArrayUtils::iteratorToArray($data); 
     } 

     if (!is_array($data)) { 
      throw new \Zend\Form\Exception\InvalidArgumentException(sprintf(
       '%s expects an array or Traversable argument; received "%s"', 
       __METHOD__, 
       (is_object($data) ? get_class($data) : gettype($data)) 
      )); 
     } 

     $data = static::assertCollectionPlaceholders($this, $data); 

     $this->hasValidated = false; 
     $this->data   = $data; 
     $this->populateValues($data); 

     return $this; 
    } 
} 

通過這樣做,表單和/或其字段集告訴他們水化器集合是空的,並且在Doctrine的水化器的情況下,提示他們移除集合中沒有的元素。