symfony表单将实体与另一个OneToMany / ManyToOne实体持久化

时间:2018-07-12 13:09:57

标签: doctrine-orm orm entity-relationship symfony4

这就是这种情况,我有 Users Profiles 。因为我需要临时的开始日期和结束日期,所以这是一个ManyToMany关系。

我的实体看起来像:

用户←一对多→ UserProfile ←一对多→ Profile

因此,我按照本文所示进行了映射:  https://www.future500.nl/articles/2013/09/doctrine-2-how-to-handle-join-tables-with-extra-columns/

这是我的实体代码:

用户

/**
 * UserProfile Collection
 * @var Collection
 *
 * @ORM\OneToMany(targetEntity="App\Entity\UserProfile", mappedBy="user", cascade={"persist", "remove"}, orphanRemoval=TRUE)
 */
private $userprofiles;

//Getters and Setters
/**
 * @return Collection|UserProfile[]
 */
public function getUserprofiles(): Collection
{
    return $this->userprofiles;
}

public function addProfile(UserProfile $user_profile): self
{
    if (!$this->userprofiles->contains($user_profile)) {
        $this->userprofiles[] = $user_profile;
        $user_profile->setUser($this);
    }

    return $this;
}

public function removeProfile(UserProfile $user_profile): self
{
    if ($this->userprofiles->contains($user_profile)) {
        $this->userprofiles->removeElement($user_profile);
        $user_profile->setUser(null);
    }

    return $this;
}

用户个人资料

/**
 * @var User
 * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="userprofiles")
 * @ORM\JoinColumn(name="User_id", referencedColumnName="id", nullable=true)
 */
private $user;

/**
 * @var Profile
 * @ORM\ManyToOne(targetEntity="App\Entity\Profile", inversedBy="users")
 * @ORM\JoinColumn(name="Profile_id", referencedColumnName="id", nullable=true)
 */
private $profile;

/**
 * @ORM\Column(type="datetime", nullable=true)
 */
private $beginning;

/**
 * @ORM\Column(type="datetime", nullable=true)
 */
private $ending;

//Getters and Setters
public function getUser(): ?User
{
    return $this->user;
}

public function setUser(?User $user): self
{
    $this->user = $user;

    return $this;
}

public function getProfile(): ?Profile
{
    return $this->profile;
}

public function setProfile(?Profile $profile): self
{
    $this->profile = $profile;

    return $this;
}

个人资料

/**
 * @var Collection
 *
 * @ORM\OneToMany(targetEntity="App\Entity\UserProfile", mappedBy="profile", cascade={"persist","remove"}, orphanRemoval=TRUE)
 */
private $users;

//Getters and Setters
/**
 * @return Collection|UserProfile[]
 */
public function getUsers(): Collection
{
    return $this->users;
}

public function addUser(?UserProfile ...$user_profiles): self
{
    foreach ($user_profiles as $user_profile){
        if (!$this->users->contains($user_profile)) {
            $this->users[] = $user_profile;
            $user_profile->setProfile($this);
        }
    }

    return $this;
}

public function removeUser(UserProfile $user_profile): self
{
    if ($this->users->contains($user_profile)) {
        $this->users->removeElement($user_profile);
        $user_profile->setProfile(null);
    }

    return $this;
}

public function getUsersConnected(  ) {
    return array_map(function (UserProfile $userProfile){
        return $userProfile->getProfile();
    }, $this->users->toArray());
}

对于表单,我希望能够在创建新的 Profile 时添加 Users ,因此我创建了一个填充到 Profile 的 CollectionType UserProfileType

个人资料类型

        ->add('users', CollectionType::class, array(
            'entry_type' => UserProfileType::class,
            'entry_options' => ['label' => false],
            'allow_add' => true,
            'allow_delete' => true
        ));

UserProfileType

    $builder
        ->add('beginning')
        ->add('ending')
        ->add('user', EntityType::class, array(
            'choice_label' => 'username',
            'class' => User::class,
            'property_path' => 'user',
            'multiple' => false,
            'expanded' => false,
            'error_bubbling' => true,
            'constraints' => [
                new NotBlank(['message' => 'User is required.'])
            ]
        ));

使用集合的原型表单,我可以为我的新 Profile 创建尽可能多的 Users 用户。问题是,配置文件的ID 没有在联合表( UserProfile 实体)中注册,但是用户的ID 却存在;我问如果其中一个ID不存在,是否可以在Symfony中保留关系?在 OneToMany / ManyToOne 模式的情况下,form :: handleRequest()方法可以管理此问题吗?

我知道从 Symfony-demo 项目的带有标签的帖子示例的 JoinTable 批注是可能的。

我正在使用Symfony 4.1.1,谢谢您的宝贵时间!

EDIT_1

经过一些试验,我尝试在创建表单时使用 empty_data Profile 的实例传递给CollectionType中的 UserProfiles 属性:

        ->add('users', CollectionType::class, array(
            'entry_type' => UserProfileType::class,
            'entry_options' => ['label' => false, 'empty_data' => new UserProfile(null, $option['data'])],
            'allow_add' => true,
            'allow_delete' => true
        ));

然后在 HiddenType 字段中检索配置文件,如下所示:

        ->add('profile', HiddenType::class, array(
            'data' => $builder->getEmptyData()->getProfile()
        ));

问题在于,Doctrine抛出一个错误,指出该实体在尝试获取配置文件的ID时不受管理。在演示中,我肯定认为Doctrine使用持久性后事件订阅者来处理此问题,因为它需要新实体的ID。

0 个答案:

没有答案