什么';插入数据一对多关系symfony4的最佳方法是什么?
这很简单,我从公司和用户那里做了一个权限表,我必须存储用户id和公司id,现在我有这个,我得到了这个错误 关联字段“App\Entity\User#$companyUserPermissionMaps”的类型“App\Entity\CompanyUserPermissionMap”的预期值改为“App\Entity\Company” 用户实体什么';插入数据一对多关系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") */
/**
* @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这听起来很奇怪,你修改过你的控制器代码吗?因为那是必要的。无论如何,你现在应该对代码的外观做一个大概的说明,因为目前还不清楚你应用了哪些更改。