2017-09-05 42 views
0

我正在使用一些工具和Symfony 3 bin/console原則創建一個簡單項目「從零到CRUD」的bash腳本:生成:* 它工作正常,但在M:N關聯的情況下,我無法從反面更新數據。 我在這裏閱讀了一些答案,我開始了一些測試,但我在「cascade = {」all「}」選項,'by_reference'=> false和其他建議之間感到困惑。 從正式的學說文件中學習這個基本的例子,最簡單的方法是什麼?如何從反面編輯/更新Symfony 3中的多對多關係

/** @Entity */ 
class User { 
    // ... 

    /** 
    * Many Users have Many Groups. 
    * @ManyToMany(targetEntity="Group", inversedBy="users") 
    */ 
    private $groups; 

    public function __construct() { 
     $this->groups = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

    // ... 
} 

/** @Entity */ 
class Group { 

    // ... 
    /** 
    * Many Groups have Many Users. 
    * @ManyToMany(targetEntity="User", mappedBy="groups") 
    */ 
    private $users; 

    public function __construct() { 
     $this->users = new \Doctrine\Common\Collections\ArrayCollection(); 
    } 

    // ... 
} 

回答

1

下面是Symfony和Doctrine中多對多關係的完整示例。我通常使用yaml而不是註釋。因此,如果要使用註釋,則必須使用註釋將自己的代碼轉換爲自己的代碼。

# AppBundle/Entity/User.php 
//the id + more fields here if needed 
//getters and setters for the other fields 

/** 
* @var \Doctrine\Common\Collections\Collection 
*/ 
private $groups; 

public function __construct() 
{ 
    $this->groups = new \Doctrine\Common\Collections\ArrayCollection(); 
} 

/** 
* Add group 
* 
* @param \AppBundle\Entity\Group $group 
* 
* @return User 
*/ 
public function addGroup(\AppBundle\Entity\Group $group) 
{ 
    if ($this->groups->contains($group)) { 
     return; 
    } 

    //those two lines of code are the one you are seeking for, for saving both the owning side and the inverse side 
    $this->groups[] = $group; 
    $group->addUser($this); 

    return $this; 
} 

/** 
* Remove group 
* 
* @param \AppBundle\Entity\Group $group 
*/ 
public function removeGroup(\AppBundle\Entity\Group $group) 
{ 
    if (!$this->groups->contains($group)) { 
     return; 
    } 

    //those are the lines for removing the owning side and the inverse side 
    $this->groups->removeElement($group); 
    $group->removeUser($this); 
} 

/** 
* Get groups 
* 
* @return \Doctrine\Common\Collections\Collection 
*/ 
public function getGroups() 
{ 
    return $this->groups; 
} 

# AppBundle/Resources/config/doctrine/User.orm.yml 
AppBundle\Entity\User: 
type: entity 
table: users 
repositoryClass: AppBundle\Repository\UserRepository 
id: 
    id: 
     type: integer 
     id: true 
     generator: 
      strategy: AUTO 
manyToMany: 
    groups: 
     targetEntity: AppBundle\Entity\Group 
     inversedBy: users 
     joinTable: 
      name: groups_users 
      joinColumns: 
       user_id: 
        referencedColumnName: id 
        nullable: true 
      inverseJoinColumns: 
       group_id: 
        referencedColumnName: id 
     cascade: ['persist', 'remove'] 
     fetch: EAGER 
fields: 
    # more fields here if needed 
lifecycleCallbacks: { } 

# AppBundle/Entity/Group.php 
//the id + more fields here if needed 
//getters and setters for the other fields 

/** 
* @var \Doctrine\Common\Collections\Collection 
*/ 
private $users; 

public function __construct() 
{ 
    $this->users = new \Doctrine\Common\Collections\ArrayCollection(); 
} 

/** 
* Add user 
* 
* @param \AppBundle\Entity\User $user 
* 
* @return Group 
*/ 
public function addUser(\AppBundle\Entity\User $user) 
{ 
    if ($this->users->contains($user)) { 
     return; 
    } 

    //these lines saves both the inverse side and the owning side 
    $this->users[] = $user; 
    $user->addGroup($this); 

    return $this; 
} 

/** 
* Remove user 
* 
* @param \AppBundle\Entity\User $user 
*/ 
public function removeUser(\AppBundle\Entity\User $user) 
{ 
    if (!$this->users->contains($user)) { 
     return; 
    } 

    //these lines remove both the inverse side and the owning side 
    $this->users->removeElement($user); 
    $user->removeGroup($this); 
} 

/** 
* Get users 
* 
* @return \Doctrine\Common\Collections\Collection 
*/ 
public function getUsers() 
{ 
    return $this->users; 
} 

# AppBundle/Resources/config/doctrine/Group.orm.yml 
AppBundle\Entity\Group: 
type: entity 
table: groups 
repositoryClass: AppBundle\Repository\GroupRepository 
id: 
    id: 
     type: integer 
     id: true 
     generator: 
      strategy: AUTO 
manyToMany: 
    users: 
     targetEntity: AppBundle\Entity\User 
     mappedBy: groups 
     cascade: ['persist'] 
     fetch: EAGER 
fields: 
    # more fields here if needed 
lifecycleCallbacks: { } 

我希望我沒有做出的任何錯誤,因爲我適應我的本地Category - 在你的Product例子。

接下來,您需要在每種表單類型中都有一個字段,以便能夠爲用戶選擇組和用戶。

# AppBundle/Form/UserType.php 
$builder 
    ->add('name') // this is a field I used in my local example, you can add yours 
    ->add('groups', EntityType::class, [ 
     'class' => 'AppBundle:Group', 
     'placeholder' => 'Choose a Group', 
     'query_builder' => function (EntityRepository $er) { 
      return $er->createQueryBuilder('g') 
       ->orderBy('g.name', 'DESC'); 
     }, 
     'choice_label' => 'name', 
     'multiple'=>true, 
     'expanded'=>false, 
     'by_reference' => false, 
    ]) 

# AppBundle/Form/GroupType.php 
$builder 
    ->add('name') 
    ->add('users', EntityType::class, [ 
     'class' => 'AppBundle:User', 
     'placeholder' => 'Choose User', 
     'query_builder' => function (EntityRepository $er) { 
      return $er->createQueryBuilder('u') 
       ->orderBy('u.name', 'DESC'); 
     }, 
     'choice_label' => 'name', 
     'multiple'=>true, 
     'expanded'=>false, 
     'by_reference' => false, 
    ]) 

在進行更新之前的模式,您需要同時創建您的實體,沒有任何映射。然後更新模式,然後繼續創建實體之間的多對多關係,並再次更新模式以應用關係。試一試,讓我們知道它是否有效。

+0

它的工作原理!謝謝。關鍵是buildForm()中的「by_reference」=> false('multiple'=> true),因爲此頁面顯示爲: https://symfony.com/doc/current/reference/forms/types/collection.html#通過引用 (顯然需要在類GroupType中添加「使用Symfony \ Bridge \ Doctrine \ Form \ Type \ EntityType;」 ) – user1619517