2013-06-11 33 views
1

我「米有一點麻煩,使用學說的ObjectSelect上多對一關係。使用Zend Framework 2 ObjectSelect和多對一的關係+ Doctrine2.3

我有以下使用多對多的工作100%添加和編輯的關係。我的編輯形式填充當前選擇沒有任何問題。

問題與多對一的關係出現,它出現的形式不被填充了當前的選擇。

我已經嘗試過傾銷的任務實體我將它綁定到表單上,它看起來100%正確,我的所有關係都是填充在實體中。

但是在綁定它之後,窗體顯示時沒有選擇當前值。

任務實體:

/** 
* @ORM\Entity 
* @ORM\Table(name="tasks") 
*/ 
class Task 
{ 

     /** 
     * @ORM\Id 
     * @ORM\Column(type="integer"); 
     * @ORM\GeneratedValue(strategy="AUTO") 
     */ 
     protected $id; 
    ... 
     /** 
     * @ORM\ManyToOne(targetEntity="Category") 
     * @ORM\JoinColumn(name="category_id", referencedColumnName="id") 
     */ 
     protected $category; 
    ...  
     /** 
     * @ORM\ManyToMany(targetEntity="ZDUser\Entity\User") 
     * @ORM\JoinTable(name="tasks_assigned_user_linker", 
     *  joinColumns={@ORM\JoinColumn(name="task_id", referencedColumnName="id")}, 
     *  inverseJoinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")} 
     *) 
     */ 
     protected $assignedUsers; 

     /** 
     * Initialize 
     */ 
     public function __construct() 
     { 
       $this->assignedUsers = new ArrayCollection(); 
     } 

     /** 
     * We need a few getters and setters 
     */ 
     public function getId() 
     { 
       return $this->id; 
     } 
     public function setId($id) 
     { 
       $this->id = $id; 
     } 

     public function getCategory() { 
       return $this->category; 
     } 
     public function setCategory(Category $category) { 
       $this->category = $category; 
     } 

     public function getAssignedUsers() { 
       return $this->assignedUsers; 
     } 
     public function addAssignedUsers(Collection $users) { 
       foreach ($users as $user) { 
         $this->assignedUsers->add($user); 
       } 
     } 
     public function removeAssignedUsers(Collection $users) { 
       foreach ($users as $user) { 
         $this->assignedUsers->removeElement($user); 
       } 
     } 
} 

我使用多對一在我的大多數實體的,我覺得這種方式更容易一些,可擴展的前進。我可以添加addtional實體並將它們鏈接到其他實體,而無需在雙方進行關係。

類別實體

/** 
* @ORM\Entity 
* @ORM\Table(name="task_categories") 
* @property int $id 
* @property string $name 
*/ 
class Category 
{ 
     /** 
     * @ORM\Id 
     * @ORM\Column(type="integer"); 
     * @ORM\GeneratedValue(strategy="AUTO") 
     */ 
     protected $id; 

     /** 
     * @ORM\Column(type="string", nullable=false) 
     */ 
     protected $name; 
    ... 
     /** 
     * Setters and getters we need 
     */ 
     public function getId() 
     { 
       return $this->id; 
     } 
     public function setId($id) 
     { 
     $this->id = (int) $id; 
     } 

     public function getName() 
     { 
       return $this->name; 
     } 
     public function setName($name) 
     { 
       $this->name = $name; 
     } 

} 

用戶實體:

/** 
* @ORM\Entity 
* @ORM\Table(name="users") 
*/ 
class User implements UserInterface, ProviderInterface 
{ 
     /** 
     * @ORM\Id 
     * @ORM\Column(type="integer") 
     * @ORM\GeneratedValue(strategy="AUTO") 
     */ 
     protected $id; 
    ... 
     /** 
     * @ORM\ManyToMany(targetEntity="ZDUser\Entity\Group") 
     * @ORM\JoinTable(name="users_groups_linker", 
     *  joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}, 
     *  inverseJoinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")} 
     *) 
     */ 
     protected $groups; 

     /** 
     * Initialies the object 
     */ 
     public function __construct() 
     { 
       $this->groups = new ArrayCollection(); 
     } 

     /* Getters and setters, we must define these for the implementation to work */ 
     public function getId() 
     { 
       return $this->id; 
     } 
     public function setId($id) 
     { 
       $this->id = (int) $id; 
     } 

     /* Get and add groups */ 
     public function getGroups() 
     { 
      return $this->groups; 
     } 
     public function addGroup(Group $group) 
     { 
      $this->groups->add($group); 
     } 

表單代碼:

class TaskForm extends Form implements ObjectManagerAwareInterface 
{ 
     protected $objectmanager; 

     public function __construct(EntityManager $em) 
     { 
       // we want to ignore the name passed 
       parent::__construct('task'); 


       $this->setHydrator(new DoctrineHydrator($em,'TaskList\Entity\Task')); 

       $this->setAttribute('method', 'post'); 
       $this->add(array(
         'name' => 'id', 
         'attributes' => array(
           'type' => 'hidden', 
         ), 
       )); 

       $this->add(array(
         'name' => 'subject', 
         'type' => 'Text', 
         'options' => array(
           'label' => 'Subject', 
         ), 
       )); 

       $this->add(array(
         'name' => 'category', 
         'type' => 'DoctrineModule\Form\Element\ObjectSelect', 
         'options' => array(
           'label' => "Category", 
           'object_manager' => $em, 
           'target_class' => 'TaskList\Entity\Category', 
           'property' => 'name', 
         ), 
       )); 


       $this->add(array(
         'name' => 'assignedUsers', 
         'type' => 'DoctrineModule\Form\Element\ObjectSelect', 
         'attributes' => array(
           'multiple' => 'multiple', 
         ), 
         'options' => array(
           'label' => "Assigned To (User)", 
           'object_manager' => $em, 
           'target_class' => 'ZDUser\Entity\User', 
           'property' => 'email', 
         ), 
       )); 

控制器編輯&地址:

public function addAction() 
    { 
      $this->addedit(); 

      // Grab form 
      $form = new TaskForm($this->getEntityManager()); 

      // Grab any request we may have 
      $request = $this->getRequest(); 

      // If it a post ... 
      if ($request->isPost()) { 
        $task = new Task(); 
        $form->bind($task); 

        // Populate data 
        $form->setData($request->getPost()); 

        // Check if the form is valid 
        if ($form->isValid()) { 
          // Setup some things we need 
          $task->setCreated(new \DateTime("now")); 

          // Save 
          $this->getEntityManager()->persist($task); 
          $this->getEntityManager()->flush(); 

          // Redirect to list of tasks 
          return $this->redirect()->toRoute('tasklist'); 
        } 
      } 

      return array(
        'form' => $form 
      ); 
    } 


    public function editAction() 
    { 
      $this->addedit(); 

      // Get ID or redirect 
      $id = (int)$this->getEvent()->getRouteMatch()->getParam('id'); 
      if (!$id) { 
        return $this->redirect()->toRoute('tasklist'); 
      } 

      // Create a form 
      $form = new TaskForm($this->getEntityManager()); 

      // Grab entity from doctrine 
      $task = $this->getEntityManager()->find('TaskList\Entity\Task', $id); 

      // Bind the form to the task 
      $form->bind($task); 

      // Check if we have a request and if its POST 
      $request = $this->getRequest(); 

      if ($request->isPost()) { 
        // If it is, set the form data from the request 
        $form->setData($request->getPost()); 

        // If the form is valid, bind the values 
        if ($form->isValid()) { 
          // Setup some things we need 
          $task->setLastUpdated(new \DateTime("now")); 

          // Flush the update 
          $this->getEntityManager()->flush(); 

          // Redirect to list of tasks 
          return $this->redirect()->toRoute('tasklist'); 
        } 
      } 

      return array(
        'id' => $id, 
        'form' => $form, 
      ); 
    } 

我很確定我錯過了一些非常簡單的事情。

回答

0

我有類似的問題,請參閱DoctrineORMModule GitHub上的this issue以獲取更多信息。

當代理實體加載時,它與Doctrine沒有從元數據返回正確的ID字段有關。解決方案如下:

  1. 等待在Doctrine 2.4中正式修復(您現在可以安裝2.4-beta2!)。
  2. 子類的ObjectSelect強制使用正確的ID字段(上述問題中的人做了這個)。
  3. 補丁DoctrineModule與此:

    --- doctrine/doctrine-module/src/DoctrineModule/Form/Element/Proxy.php 2013-03-11 17:49:55.406011600 -0300 
    +++ doctrine/doctrine-module/src/DoctrineModule/Form/Element/Proxy.php 2013-03-11 17:51:33.592710900 -0300 
    @@ -240,7 +240,10 @@ 
           if (count($identifier) > 1) { 
            //$value = $key; 
           } else { 
    -     $value = current($metadata->getIdentifierValues($value)); 
    +     // Doctrine has a bug that makes the following not work, 
    +     // this is a horrible workaround until Doctrine 2.4 is released with a fix. 
    +     //$value = current($metadata->getIdentifierValues($value)); 
    +     $value = $value->getId(); 
           } 
          } 
         } 
    

$value->getId()的依賴於該方法中的相應實體可用。這不是建議,但一個快速修復。

+0

可能不是正確的方式?我把我的想法發佈到他們的ML :) –

+0

他們已經在2.4中修復了它:) –

+0

你有鏈接到提交嗎? –

0

可能不是正確的方法?我把我的想法發佈到他們的ML :) 可能不是正確的方法?我把我的想法發佈到他們的ML :)

diff --git a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php 
index cba525a..2f62375 100644 
--- a/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php 
+++ b/vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php 
@@ -667,7 +667,17 @@ class ClassMetadataInfo implements ClassMetadata 
      return $id; 
     } 

-  $value = $this->reflFields[$this->identifier[0]]->getValue($entity); 
+ 
+    /** 
+    * NK: First try use the getter, in the case of a proxied object, the reflection is not going to work 
+    * as the proxied object does not have any properties 
+    */ 
+    $getter = 'get' . ucfirst($this->identifier[0]); 
+    if (method_exists($entity, $getter)) { 
+      $value = $entity->$getter(); 
+    } else { 
+    $value = $this->reflFields[$this->identifier[0]]->getValue($entity); 
+    }