什么';插入数据一对多关系symfony4的最佳方法是什么?

什么';插入数据一对多关系symfony4的最佳方法是什么?,symfony,doctrine,symfony4,Symfony,Doctrine,Symfony4,这很简单,我从公司和用户那里做了一个权限表,我必须存储用户id和公司id,现在我有这个,我得到了这个错误 关联字段“App\Entity\User#$companyUserPermissionMaps”的类型“App\Entity\CompanyUserPermissionMap”的预期值改为“App\Entity\Company” 用户实体 /** * @ORM\Id() * @ORM\GeneratedValue() * @ORM\Column(type="integer") */

这很简单,我从公司和用户那里做了一个权限表,我必须存储用户id和公司id,现在我有这个,我得到了这个错误

关联字段“App\Entity\User#$companyUserPermissionMaps”的类型“App\Entity\CompanyUserPermissionMap”的预期值改为“App\Entity\Company”

用户实体

/**
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $userId;

/**
 * @ORM\Column(type="string", length=12)
 */
private $code;

/**
 * @ORM\Column(type="string", length=180, unique=true)
 */
private $email;


/**
 * @var CompanyUserPermissionMap[]
 * @ORM\OneToMany(targetEntity="App\Entity\CompanyUserPermissionMap", mappedBy="user", orphanRemoval=true)
 */
private $companyUserPermissionMaps;


public function __construct()
{
    $this->companyUserPermissionMaps = new ArrayCollection();
}


public function getCompanyUserPermissionMaps(): Collection
{
    return $this->companyUserPermissionMaps;
}

public function addCompanyUserPermissionMaps(CompanyUserPermissionMaps $permission): self
{
    if (!$this->companyUserPermissionMaps->contains($permission)) {
        $this->companyUserPermissionMaps[] = $permission;
        $permission->setUser($this);
    }

    return $this;
}
公司实体

#########################
##      PROPERTIES     ##
#########################

/**
 * @ORM\Id()
 * @ORM\GeneratedValue()
 * @ORM\Column(type="integer")
 */
private $companyId;

/**
 * @ORM\Column(type="string", length=6, unique=true)
 */
private $code;



/**
 * @var CompanyUserPermissionMap[]
 * @ORM\OneToMany(targetEntity="App\Entity\CompanyUserPermissionMap", mappedBy="company", orphanRemoval=true)
 */
private $companyUserPermissionMaps;


public function __construct()
{
    $this->companyUserPermissionMaps = new ArrayCollection();

}



/**
 * @return Collection|CompanyUserPermissionMaps[]
 */
public function getCompanyUserPermissionMaps(): Collection
{
    return $this->companyUserPermissionMaps;
}

public function addCompanyUserPermissionMaps(AccountingBankPermission $permission): self
{
    if (!$this->companyUserPermissionMaps->contains($permission)) {
        $this->companyUserPermissionMaps[] = $permission;
        $permission->setAccount($this);
    }

    return $this;
}

public function removeCompanyUserPermissionMaps(AccountingBankPermission $permission): self
{
    if ($this->companyUserPermissionMaps->contains($permission)) {
        $this->companyUserPermissionMaps->removeElement($permission);
        // set the owning side to null (unless already changed)
        if ($permission->getAccount() === $this) {
            $permission->setAccount(null);
        }
    }

    return $this;
}
关系表

Column(type="integer")

private $companyUserPermissionId;


/**
 * @var User
 * @ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="companyUserPermissionMaps")
 * @ORM\JoinColumn(referencedColumnName="user_id", nullable=false)
 */
private $user;

/**
 * @var Company
 * @ORM\ManyToOne(targetEntity="App\Entity\Company", inversedBy="companyUserPermissionMaps")
 * @ORM\JoinColumn(referencedColumnName="company_id", nullable=true)
 */
private $company;


/**
 * @return int|null
 */
public function getCompanyUserPermissionId(): ?int
{
    return $this->companyUserPermisionId;
}



/**
 * @return User
 */
public function getUser(): ?User
{
    return $this->user;
}

/**
 * @param User $user
 * @return AccountingBankPermission
 */
public function setUser(?User $user): self
{
    $this->user = $user;
    return $this;
}

/**
 * @return Company
 */
public function getCompany(): ?Company
{
    return $this->company;
}

/**
 * @param array $company
 * @return CompanyUserPermissionMap
 */
public function setCompany(?array $company): self
{
    $this->company = $company;
    return $this;
}
表格类型

 $builder
            ->add('roles' ,ChoiceType::class ,[
                'required'  => true,
                'choices' => $this->roles,
                'multiple' => true,
                'expanded' => true,
                'label_attr' => [
                    'class' => 'custom-control-label',
                ],
                'choice_attr' => function($val, $key, $index) {
                    return ['class' => 'custom-control-input'];
                },
                'attr'=>['class' =>'custom-checkbox custom-control']
            ])
            ->add('email', EmailType::class, [
                'label' => "E-Mail"
            ])
            ->add('firstName', TextType::class, [
                'label' => "First Name"
            ])
            ->add('lastName', TextType::class, [
                'label' => "Last Name"
            ])
            ->add('companyUserPermissionMaps' ,EntityType::class ,[
                'required' => true,
                'class'    => Company::class,
                'label'    => 'Compañia',
                'multiple' => true,
                'expanded' => false,
                'choice_label'  => 'legalName',
                'mapped'=>false
            ])
            ->add('save', SubmitType::class, [
                'label' => "Save"
            ])
我的控制器函数如下所示

 $user = new User();

    $originalRoles = $this->getParameter('security.role_hierarchy.roles');

    $options=['roles' => $originalRoles ];

    $form = $this->createForm(UserType::class, $user, $options);

    $form->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {

        $tempPassword = "some pass";

        $user->setPassword($encoder->encodePassword(
            $user,
            $tempPassword
        ));

        $companies=[];
        $companiesForm=$form->get('companyUserPermissionMaps')->getData();
        foreach ($companiesForm as $value) {
            $companies[] = $value->getCompanyId();
        }

        // Save object to database
        $entityManager = $this->getDoctrine()->getManager();

        /** @var CompanyRepository $companyRepository */
        $companyRepository = $this->getDoctrine()->getRepository(Company::class);
        $companiesArr =$companyRepository->findCompanyByArray($companies);
        $companyUserPermissionMap = new CompanyUserPermissionMap();
        $companyUserPermissionMap->setUser($user);
        $companyUserPermissionMap->setCompany($companiesArr);

        $entityManager->persist($user);
        $entityManager->persist($companyUserPermissionMap);

更新

好吧,我忘了提你实际上面临的问题。表单组件虽然很智能,但在加载/修改表单数据时会尝试调用getter和setter。由于表单包含
->add('companyUserPermissionMaps',…
),表单组件将调用实体上的
getCompanyUserPermissionMaps
(该组件将返回当前可能为空的集合)并将尝试通过
setCompanyUserPermissionMaps
add
/
remove
而不是
set
向实体回写(如果存在)

由于您的字段实际上的行为就好像它包含一组
公司
对象,因此
用户
对象上的设置显然会失败,并显示错误消息:

关联字段“App\Entity\User#$companyUserPermissionMaps”的类型“App\Entity\CompanyUserPermissionMap”的预期值改为“App\Entity\Company”

这绝对有道理。因此,这个问题可以用不同的方法解决。您显然已经尝试过的一种方法是将
映射为
false
,而不是
false
您使用的
'false'
(注意引号),其计算结果为真……具有讽刺意味的是。因此,要使用您的方法,您必须删除引号。然而,我提出了一种不同的方法,我更喜欢这种方法

结束更新

我的一般建议是隐藏您不想显示的内容。因此,在表单生成器中,而不是

->add('companyUserPermissionMaps', EntityType::class, [
    'required' => true,
    'class'    => Company::class,
    'label'    => 'Compañia',
    'multiple' => true,
    'expanded' => false,
    'choice_label'  => 'legalName',
    'mapped'=>'false'
])
显然,它已经不是一个处理
CompanyUserPermissionMaps
的字段,而是一个处理companys的字段-因此,显然您怀疑这在语义上有所不同,您应该返回到
User
实体,并为其提供一个函数
getcompanys

public function getCompanies() {
    return array_map(function ($map) {
        return $map->getCompany();
    }, $this->getCompanyUserPermissionsMaps());
}
public function addCompany(Company $company) {
    foreach($this->companyUserPermissionMaps->toArray() as $map) {
        if($map->getCompany() === $company) {
            return;
        }
    }
    $new = new CompanyUserPermissionMap();
    $new->setCompany($company);
    $new->setUser($this);
    $this->companyUserPermissionMaps->add($new);
}
public function removeCompany(Company $company) {
    foreach($this->companyUserPermissionMaps as $map) {
        if($map->getCompany() == $company) {
            $this->companyUserPermissionMaps->removeElement($map);
        }
    }
}
然后,您将调用字段
companys
(因此
->add('companys',…)
)并对
Company
实体采取行动,而不是那些烦人的映射。(我也不太喜欢将
数组集合
和其他内部结构暴露在外部。但是,嘿,这是您的决定。)


但是,如果您的映射在某一点上要保存更多的值,您实际上必须在表单中使用映射,而不仅仅是使用
公司
实体。

用户实体
中是否正常。函数addCompanyUserPermissionMaps(CompanyUserPermissionMaps$per…
CompanyUserPermissionMaps
带有一个“s”?这不是
CompanyUserPermissionMap
?是的,你是对的,问题是我需要保存多个公司并将它们分配给一个用户。为什么不让条令处理如下关系:(将您的公司实体替换为示例中的集团实体)嘿,谢谢你花时间回答这个问题,Jakumi,问题是我需要选择多个公司并将其分配给这个用户,看看我刚才添加的控制器功能that@KevinLincon表单组件识别集合,并将自动使用
add[fieldname]
remove[fieldname]
如果存在,或
在实体上设置[fieldname]s
(或正确的复数形式),以将所做的更改应用于表单组件中的集合。这可能就是您出现错误的原因,因为表单组件实际上试图添加公司(到您声明的字段),但您的实体不支持将公司添加为…映射。您的控制器试图规避此问题,但效率低下。@KevinLincon我刚刚注意到一个小细节导致了您的错误,将其添加到我的答案开头;o)您完全正确,但问题是我无法插入数据,我更新了您告诉我的内容以及联接表上的setCompany,但仍然获得了>>关联字段“App\Entity\CompanyUserPermissionMap#$Company”类型为“App\Entity\Company”的预期值,获得了“array”取而代之的是。@KevinLincon这听起来很奇怪,你修改过你的控制器代码吗?因为那是必要的。无论如何,你现在应该对代码的外观做一个大概的说明,因为目前还不清楚你应用了哪些更改。