Я пытаюсь добавить пользователей в свою форму назначения в Symfony 4, но при попытке загрузить форму получаю следующее исключение:
Could not load type "App\Entity\User": class does not implement "Symfony\Component\Form\FormTypeInterface".
Я написал следующий код:
AssigmentFormType.php:
class AssignmentFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('name')
->add('description', TextareaType::class
)
->add('deadline', DateType::class, array(
'empty_data' => array(
'year' => date('Y'), 'month' => date('M'), 'day' => date('d'),
)
))
->add('status')
->add('story', TextareaType::class)
->add('company', EntityType::class, array(
'class' => Company::class,
'choice_label' => 'name',
'placeholder' => 'Select a value',
'empty_data' => null,
))
->add('user', CollectionType::class, array(
'entry_type' => User::class,
'entry_options' => array('label' => false),
'allow_add' => true
))
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Assignment::class,
]);
}
}
AssignmentController:
class AssignmentController extends Controller
{
/**
* @Security("is_authenticated()")
* @Route("/assignments", name = "assignments")
*/
public function index(Request $request)
{
$assignment_rep = $this->getDoctrine()->getRepository(Assignment::class);
if ($request->get('search') == null) {
$companies = $assignment_rep->findAll();
}
else{
$companies = $assignment_rep->search($request->get('search'));
}
$page = $request->query->get('page', 1);
$adapter = new ArrayAdapter($companies);
$pagerfanta = new Pagerfanta($adapter);
$pagerfanta->setMaxPerPage(25);
$pagerfanta->setCurrentPage($page);
$companies = $pagerfanta->getCurrentPageResults();
return $this->render('assignment/index.html.twig', array(
'assignments' => $companies,
'pager' => $pagerfanta
));
}
/**
* @Route("/assignment/new", name = "newAssignment")
* @IsGranted("ROLE_ADMIN")
*/
public function add(Request $request)
{
$form = $this->createForm(AssignmentFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$this->addFlash('success', 'Assignment added');
$company = $form->getData();
$em = $this->getDoctrine()->getManager();
$em->persist($company);
$em->flush();
return $this->redirectToRoute('assignments');
}
return $this->render('assignment/edit.html.twig', array(
'form' => $form->createView()
));
}
}
Assignment.php
class Assignment
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type = "integer")
*/
private $id;
/**
* @ORM\Column(type = "string", length=255)
*/
private $name;
/**
* @ORM\Column(type = "datetime", nullable=true)
*/
private $deadline;
/**
* @ORM\Column(type = "string", length=255, nullable=true)
*/
private $description;
/**
* @ORM\Column(type = "string", length=255, nullable=true)
*/
private $status;
/**
* @ORM\Column(type = "string", length=255, nullable=true)
*/
private $story;
/**
* @ORM\ManyToOne(targetEntity = "App\Entity\Company", inversedBy = "assignments")
* @ORM\JoinColumn(nullable=false)
*/
private $company;
/**
* @ORM\ManyToMany(targetEntity = "App\Entity\User", inversedBy = "assignments")
*/
private $user;
/**
* @ORM\OneToMany(targetEntity = "App\Entity\Task", mappedBy = "assignment")
*/
private $tasks;
public function __construct()
{
$this->user = new ArrayCollection();
$this->tasks = new ArrayCollection();
}
public function getId()
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getDeadline(): ?\DateTimeInterface
{
return $this->deadline;
}
public function setDeadline(?\DateTimeInterface $deadline): self
{
$this->deadline = $deadline;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getStatus(): ?string
{
return $this->status;
}
public function setStatus(?string $status): self
{
$this->status = $status;
return $this;
}
public function getStory(): ?string
{
return $this->story;
}
public function setStory(?string $story): self
{
$this->story = $story;
return $this;
}
public function getCompany(): ?Company
{
return $this->company;
}
public function setCompany(?Company $company): self
{
$this->company = $company;
return $this;
}
/**
* @return Collection|User[]
*/
public function getUser(): Collection
{
return $this->user;
}
public function addUser(User $user): self
{
if (!$this->user->contains($user)) {
$this->user[] = $user;
}
return $this;
}
public function removeUser(User $user): self
{
if ($this->user->contains($user)) {
$this->user->removeElement($user);
}
return $this;
}
/**
* @return Collection|Task[]
*/
public function getTasks(): Collection
{
return $this->tasks;
}
public function addTask(Task $task): self
{
if (!$this->tasks->contains($task)) {
$this->tasks[] = $task;
$task->setAssignment($this);
}
return $this;
}
public function removeTask(Task $task): self
{
if ($this->tasks->contains($task)) {
$this->tasks->removeElement($task);
// set the owning side to null (unless already changed)
if ($task->getAssignment() === $this) {
$task->setAssignment(null);
}
}
return $this;
}
}
User.php
class User implements AdvancedUserInterface, \Serializable
{
/**
* @ORM\Column(type = "integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy = "AUTO")
*/
public $id;
/**
* @ORM\Column(type = "string", length=25, unique=true)
*/
public $username;
/**
* @ORM\Column(type = "string", length=64)
*/
public $password;
/**
* @ORM\Column(type = "string", length=128, unique=true)
* @Assert\Email()
*/
public $email;
/**
* @ORM\Column(name = "is_active", type = "boolean")
*/
public $isActive;
/**
* @ORM\Column(name = "roles", type = "array")
*/
public $roles = [];
/**
* @ORM\OneToOne(targetEntity = "App\Entity\UserDetails", mappedBy = "user", cascade = {"persist", "remove"})
*/
private $userDetails;
/**
* @ORM\ManyToMany(targetEntity = "App\Entity\Assignment", mappedBy = "user")
*/
private $assignments;
public function __construct()
{
$this->isActive = true;
$this->assignments = new ArrayCollection();
// may not be needed, see section on salt below
// $this->salt = md5(uniqid('', true));
}
/**
* @param mixed $isActive
*/
public function setIsActive($isActive)
{
$this->isActive = $isActive;
}
public function getEmail()
{
return $this->email;
}
public function setEmail($email)
{
$this->email = $email;
}
public function getUsername()
{
return $this->username;
}
public function setUsername($username)
{
$this->username = $username;
}
public function getPassword()
{
return $this->password;
}
public function setPassword($password)
{
$this->password = $password;
}
public function getSalt()
{
// The bcrypt and argon2i algorithms don't require a separate salt.
// You *may* need a real salt if you choose a different encoder.
return null;
}
public function getRoles()
{
$roles = $this->roles;
if (!in_array('ROLE_USER', $roles)) {
$roles[] = 'ROLE_USER';
}
return $roles;
}
/**
* @return mixed
*/
public function getId()
{
return $this->id;
}
public function setRoles(array $roles)
{
$this->roles = $roles;
}
public function eraseCredentials()
{
}
/** @see \Serializable::serialize() */
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->password,
$this->isActive
// see section on salt below
// $this->salt,
));
}
/** @see \Serializable::unserialize() */
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
$this->isActive
// see section on salt below
// $this->salt
) = unserialize($serialized, ['allowed_classes' => false]);
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isActive;
}
public function getUserDetails(): ?UserDetails
{
return $this->userDetails;
}
public function setUserDetails(UserDetails $userDetails): self
{
$this->userDetails = $userDetails;
// set the owning side of the relation if necessary
if ($this !== $userDetails->getUser()) {
$userDetails->setUser($this);
}
return $this;
}
/**
* @return Collection|Assignment[]
*/
public function getAssignments(): Collection
{
return $this->assignments;
}
public function addAssignment(Assignment $assignment): self
{
if (!$this->assignments->contains($assignment)) {
$this->assignments[] = $assignment;
$assignment->addUser($this);
}
return $this;
}
public function removeAssignment(Assignment $assignment): self
{
if ($this->assignments->contains($assignment)) {
$this->assignments->removeElement($assignment);
$assignment->removeUser($this);
}
return $this;
}
}
Проблема решается удалением атрибута allow_add => true в массиве, но таким образом я не могу добавлять пользователей в свое назначение. Может ли кто-нибудь помочь мне добавить пользователей в ассигмнет в форме?
@ mission712 Я не могу найти никакой документации по FormTypeInterface в Symfony4
entry_type в вашей пользовательской коллекции должен быть фактическим типом формы, а не пользовательской сущностью. По сути, вам нужно сделать себе UserType. Следуйте пример в документации.
@Cerad Но получу ли я тогда окно выбора с моими существующими пользователями? Я не хочу добавлять новых пользователей, а только добавляю в задание существующих пользователей
Похоже, вам нужен тип множественного выбора вместо коллекции.






Как говорится в комментариях, ошибка вызвана тем, что entry_type должен быть одним из типов форм Symfony. Документация здесь
Если вы хотите, чтобы в вашей форме был список существующих пользователей, вам следует вместо этого использовать Тип объекта. Он предоставляет список ваших существующих пользователей. Это также позволяет вам делать множественный выбор, если хотите.
Ошибка четко указывает, в чем проблема. Вам нужно будет реализовать
"Symfony\Component\Form\FormTypeInterface".