我已经试了好几个小时让我的多实体表单工作了,但这真的让我头疼,我发现没有一个例子能工作。
我检查了集合表单类型文档和表单集合,以及实体表单类型。
我有一个User实体、UserRole和 Role该表单显示了创建用户的字段,我希望能够为新用户选择一个新角色。因此,我尝试使用EntityType,一个select下拉列表很好地显示了所有角色(仅当我添加了mapped=>false选项时(,但在表单提交后不进行处理。它的数据不在$form->getData((中,用户被创建,user_role条目从未创建。如果我在没有映射=>false的情况下尝试,它会抛出我: 代码: 使用CollectionType时,它根本不会显示选择下拉列表。代码: 我是在控制器的代码中遗漏了什么,还是误解了Form类型的使用?我真的不知道我做错了什么。 用户实体:Could not determine access type for property "user_roles" in class "AppEntityUser": The property "user_roles" in class "AppEntityUser" can be defined with the methods "addUserRole()", "removeUserRole()" but the new value must be an array or an instance of Traversable, "AppEntityRole" given..
$form = $this->createFormBuilder(new User)
... //other add entries
->add('user_roles', EntityType::class, array(
'label' => 'Group (role)',
'class' => Role::class,
'choice_label' => 'name',
// 'mapped' => false, // Form works when false, but doesn't save/create UserRole entry
))
->getForm();
$form->handleRequest($request);
$form = $this->createFormBuilder($user)
.... //other add entries
->add('user_roles', CollectionType::class, array(
'entry_type' => ChoiceType::class,
'entry_options' => array(
'choices' => $roleChoices,
),
))
->getForm();
$form->handleRequest($request);
<?php
namespace AppEntity;
use DoctrineORMMapping as ORM;
use SymfonyComponentSecurityCoreUserUserInterface;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineCommonCollectionsCollection;
use JMSSerializerAnnotationExclude;
/**
* @ORMEntity(repositoryClass="AppRepositoryUserRepository")
* @ORMHasLifecycleCallbacks()
*/
class User implements UserInterface
{
/**
* @ORMColumn(type="string", length=255, nullable=true)
* @Exclude
*/
private $apiToken;
/**
* @ORMId()
* @ORMGeneratedValue()
* @ORMColumn(type="integer")
*/
private $id;
/**
* @ORMColumn(type="string", length=180, unique=true)
*/
private $email;
/**
* @ORMColumn(type="json_array")
*/
private $roles = [];
/**
* @ORMColumn(type="string", length=255)
*/
private $first_name;
/**
* @ORMColumn(type="string", length=255, nullable=true)
*/
private $middle_name;
/**
* @ORMColumn(type="string", length=255)
*/
private $last_name;
/**
* @ORMColumn(type="boolean")
*/
private $enabled;
/**
* @ORMColumn(type="datetime", nullable=true)
*/
private $blocked_at;
/**
* @ORMOneToMany(targetEntity="AppEntityProject", mappedBy="created_by")
*/
private $projects;
/**
* @ORMOneToMany(targetEntity="AppEntityUserRole", mappedBy="user", fetch="EAGER")
*/
private $user_roles;
/**
* @ORMOneToMany(targetEntity="AppEntityCategory", mappedBy="created_by")
*/
private $categories;
/**
* @ORMOneToMany(targetEntity="AppEntityProjectFileIos", mappedBy="created_by")
*/
private $projectFileIos;
/**
* @ORMOneToMany(targetEntity="AppEntityProjectFileAndroid", mappedBy="created_by")
*/
private $projectFileAndroid;
/**
* Generate full name
*/
private $full_name;
/**
* @var string The hashed password
* @ORMColumn(type="string")
* @Exclude
*/
private $password;
/**
* @ORMOneToMany(targetEntity="AppEntityProjectUser", mappedBy="user", fetch="EAGER")
*/
private $projectUsers;
/**
* @ORMColumn(type="datetime")
*/
private $created_at;
/**
* @ORMColumn(type="datetime")
*/
private $updated_at;
/**
* @ORMManyToOne(targetEntity="AppEntityUser", inversedBy="project")
*/
private $created_by;
/**
* @ORMManyToOne(targetEntity="AppEntityUser", inversedBy="project")
* @ORMJoinColumn(nullable=true)
*/
private $last_updated_by;
public function __construct()
{
$this->user_roles = new ArrayCollection();
$this->user_role = new ArrayCollection();
$this->categories = new ArrayCollection();
$this->projectFileIos = new ArrayCollection();
$this->projectFileAndroid = new ArrayCollection();
$this->projectUsers = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getApiToken(): ?string
{
return $this->apiToken;
}
public function setApiToken(string $apiToken): self
{
$this->apiToken = $apiToken;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUsername(): string
{
return (string) $this->email;
}
/**
* @see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* @see UserInterface
*/
public function getPassword(): string
{
return (string) $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* @see UserInterface
*/
public function getSalt()
{
// not needed when using the "bcrypt" algorithm in security.yaml
}
/**
* @see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getFirstName(): ?string
{
return $this->first_name;
}
public function setFirstName(string $first_name): self
{
$this->first_name = $first_name;
return $this;
}
public function getMiddleName(): ?string
{
return $this->middle_name;
}
public function setMiddleName(string $middle_name): self
{
$this->middle_name = $middle_name;
return $this;
}
public function getLastName(): ?string
{
return $this->last_name;
}
public function setLastName(string $last_name): self
{
$this->last_name = $last_name;
return $this;
}
public function getEnabled(): ?bool
{
return $this->enabled;
}
public function setEnabled(bool $enabled): self
{
$this->enabled = $enabled;
return $this;
}
public function getBlockedAt(): ?DateTimeInterface
{
return $this->blocked_at;
}
public function setBlockedAt(?DateTimeInterface $blocked_at): self
{
$this->blocked_at = $blocked_at;
return $this;
}
/**
* @return Collection|UserRole[]
*/
public function getUserRoles(): ?Collection
{
return $this->user_roles;
}
public function getUserRole(): ?Collection
{
return $this->user_role;
}
public function addUserRole(UserRole $userRole): self
{
if (!$this->user_role->contains($userRole)) {
$this->user_role[] = $userRole;
$user_role->setUserId($this);
}
return $this;
}
public function removeUserRole(UserRole $userRole): self
{
if ($this->user_role->contains($userRole)) {
$this->user_role->removeElement($userRole);
// set the owning side to null (unless already changed)
if ($user_role->getUserId() === $this) {
$user_role->setUserId(null);
}
}
return $this;
}
/**
* @return Collection|Project[]
*/
public function getProjects(): Collection
{
return $this->projects;
}
public function addProject(Project $project): self
{
if (!$this->project->contains($project)) {
$this->project[] = $project;
$project->setUserId($this);
}
return $this;
}
public function removeProject(Project $project): self
{
if ($this->project->contains($project)) {
$this->project->removeElement($project);
// set the owning side to null (unless already changed)
if ($project->getUserId() === $this) {
$project->setUserId(null);
}
}
return $this;
}
/**
* @return Collection|Category[]
*/
public function getCategories(): Collection
{
return $this->categories;
}
public function addCategory(Category $category): self
{
if (!$this->categories->contains($category)) {
$this->categories[] = $category;
$category->setCreatedBy($this);
}
return $this;
}
public function removeCategory(Category $category): self
{
if ($this->categories->contains($category)) {
$this->categories->removeElement($category);
// set the owning side to null (unless already changed)
if ($category->getCreatedBy() === $this) {
$category->setCreatedBy(null);
}
}
return $this;
}
/**
* @return Collection|ProjectFileIos[]
*/
public function getProjectFileIos(): Collection
{
return $this->projectFileIos;
}
public function addProjectFileIo(ProjectFileIos $projectFileIo): self
{
if (!$this->projectFileIos->contains($projectFileIo)) {
$this->projectFileIos[] = $projectFileIo;
$projectFileIo->setCreatedBy($this);
}
return $this;
}
public function removeProjectFileIo(ProjectFileIos $projectFileIo): self
{
if ($this->projectFileIos->contains($projectFileIo)) {
$this->projectFileIos->removeElement($projectFileIo);
// set the owning side to null (unless already changed)
if ($projectFileIo->getCreatedBy() === $this) {
$projectFileIo->setCreatedBy(null);
}
}
return $this;
}
/**
* @return Collection|ProjectFileAndroid[]
*/
public function getProjectFileAndroid(): Collection
{
return $this->projectFileAndroid;
}
public function addProjectFileAndroid(ProjectFileAndroid $projectFileAndroid): self
{
if (!$this->projectFileAndroid->contains($projectFileAndroid)) {
$this->projectFileAndroid[] = $projectFileAndroid;
$projectFileAndroid->setCreatedBy($this);
}
return $this;
}
public function removeProjectFileAndroid(ProjectFileAndroid $projectFileAndroid): self
{
if ($this->projectFileAndroid->contains($projectFileAndroid)) {
$this->projectFileAndroid->removeElement($projectFileAndroid);
// set the owning side to null (unless already changed)
if ($projectFileAndroid->getCreatedBy() === $this) {
$projectFileAndroid->setCreatedBy(null);
}
}
return $this;
}
public function getFullName()
{
$lastName = $this->middle_name ? $this->middle_name . ' ' : '';
$lastName .= $this->last_name;
return $this->first_name . ' ' . $lastName;
}
/**
* Triggered after entity has been loaded into the current EntityManager from de database
* or after refresh operation applied to it
* @ORMPostLoad
*/
public function postLoad()
{
$this->full_name = $this->getFullName();
}
/**
* @return Collection|ProjectUser[]
*/
public function getProjectUsers(): Collection
{
return $this->projectUsers;
}
public function addProjectUser(ProjectUser $projectUser): self
{
if (!$this->projectUsers->contains($projectUser)) {
$this->projectUsers[] = $projectUser;
$projectUser->setUser($this);
}
return $this;
}
public function removeProjectUser(ProjectUser $projectUser): self
{
if ($this->projectUsers->contains($projectUser)) {
$this->projectUsers->removeElement($projectUser);
// set the owning side to null (unless already changed)
if ($projectUser->getUser() === $this) {
$projectUser->setUser(null);
}
}
return $this;
}
public function getCreatedAt(): ?DateTimeInterface
{
return $this->created_at;
}
public function setCreatedAt(DateTimeInterface $created_at): self
{
$this->created_at = $created_at;
return $this;
}
public function getUpdatedAt(): ?DateTimeInterface
{
return $this->updated_at;
}
public function setUpdatedAt(DateTimeInterface $updated_at): self
{
$this->updated_at = $updated_at;
return $this;
}
public function getCreatedBy(): ?User
{
return $this->created_by;
}
public function setCreatedBy(?User $created_by): self
{
$this->created_by = $created_by;
return $this;
}
public function getLastUpdatedBy(): ?User
{
return $this->last_updated_by;
}
public function setLastUpdatedBy(?User $last_updated_by): self
{
$this->last_updated_by = $last_updated_by;
return $this;
}
/**
* Triggered on insert
* @ORMPrePersist
*/
public function onPrePersist()
{
$this->enabled = true;
$this->created_at = new DateTime("now");
$this->updated_at = new DateTime();
$this->roles = 'a:1:{i:0;s:9:"ROLE_USER";}';
}
/**
* Triggered on update
* @ORMPreUpdate
*/
public function onPreUpdate()
{
$this->updated_at = new DateTime("now");
}
}
在Symfony中,要获取未映射的表单数据,请尝试这样做。
$data = $form->getData();
$roles = $form->get("user_roles")->getData();
此外,注意到一件事。在下面的代码块中,类不应该是UserRole::class
而不是Role::class
吗。
$form = $this->createFormBuilder(new User)
... //other add entries
->add('user_roles', EntityType::class, array(
'label' => 'Group (role)',
'class' => Role::class,
'choice_label' => 'name',
// 'mapped' => false, // Form works when false, but doesn't save/create UserRole entry
))
->getForm();
希望这能有所帮助,干杯
您选择的一般方式是可以的。坚持使用EntityType并删除mapped=false,这将告诉Symfony忽略该字段。
我想问题是:你的类中混合了$this->user_role和$this->user_role,可能是一个重命名的变量。首先在__construct((、addUserRole((、removeUserRole。
然后添加一个方法
public function setUserRoles($userRoles)
{
$this->user_roles = new ArrayCollection();
foreach ($userRoles as $role) {
$this->addUserRole($role);
}
return $this;
}