Problem with my entity and type Symfony 6 - forms

first of all, soory for my English, I'm French.
So, I try to create a form that use many entities. Here they are :
Controller :
class SaisieController extends AbstractController
{
#[Route('/user/saisie', name: 'app_usersaisie')]
public function add(Request $request, ManagerRegistry $doctrine, EntityManagerInterface $entityManager,): Response
{
$session = new ChasseurAnimauxSession();
$form = $this->createForm(SaisieFormType::class, $session);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {//
$em = $entityManager;
$em->persist($form->getData());
$em->flush();
return $this->render('user/informationsUser.html.twig', [
'form_index' => $form->createView(),
]);
}
return $this->render('user/informationsUser.html.twig', [
'form_index' => $form->createView(),
]);
}
}
First Entity ChasseurAniamauxSession :
namespace App\Entity;
use App\Repository\ChasseurAnimauxSessionRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ChasseurAnimauxSessionRepository::class)]
class ChasseurAnimauxSession
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 10, nullable: true)]
private ?string $sexe = null;
#[ORM\Column(nullable: true)]
private ?int $poids = null;
#[ORM\OneToMany(mappedBy: 'id', targetEntity: SessionChasse::class)]
#[ORM\Column(nullable: true)]
private ?int $session_chasse_id = null;
#[ORM\OneToMany(mappedBy: 'id', targetEntity: Animaux::class)]
#[ORM\Column(nullable: true)]
private ?int $animaux_id = null;
#[ORM\OneToMany(mappedBy: 'id', targetEntity: User::class)]
#[ORM\Column(nullable: true)]
private ?int $chasseur_id = null;
#[ORM\Column(nullable: true)]
private ?int $number_bague = null;
public function getId(): ?int
{
return $this->id;
}
public function getSexe(): ?string
{
return $this->sexe;
}
public function setSexe(?string $sexe): self
{
$this->sexe = $sexe;
return $this;
}
public function getPoids(): ?int
{
return $this->poids;
}
public function setPoids(?int $poids): self
{
$this->poids = $poids;
return $this;
}
/**
* #return int|null
*/
public function getSessionChasseId(): ?int
{
return $this->session_chasse_id;
}
/**
* #param int|null $session_chasse_id
* #return ChasseurAnimauxSession
*/
public function setSessionChasseId(?int $session_chasse_id): ChasseurAnimauxSession
{
$this->session_chasse_id = $session_chasse_id;
return $this;
}
/**
* #return int|null
*/
public function getAnimauxId(): ?int
{
return $this->animaux_id;
}
/**
* #param int|null $animaux_id
* #return ChasseurAnimauxSession
*/
public function setAnimauxId(?int $animaux_id): ChasseurAnimauxSession
{
$this->animaux_id = $animaux_id;
return $this;
}
/**
* #return int|null
*/
public function getChasseurId(): ?int
{
return $this->chasseur_id;
}
/**
* #param int|null $chasseur_id
* #return ChasseurAnimauxSession
*/
public function setChasseurId(?int $chasseur_id): ChasseurAnimauxSession
{
$this->chasseur_id = $chasseur_id;
return $this;
}
public function getNumberBague(): ?int
{
return $this->number_bague;
}
public function setNumberBague(?int $number_bague): self
{
$this->number_bague = $number_bague;
return $this;
}
}
Another Entity Animaux :
namespace App\Entity;
use App\Repository\AnimauxRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: AnimauxRepository::class)]
class Animaux
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $espece = null;
public function getId(): ?int
{
return $this->id;
}
public function getEspece(): ?string
{
return $this->espece;
}
public function setEspece(?string $espece): self
{
$this->espece = $espece;
return $this;
}
}
The type :
<?php
namespace App\Form\user;
use App\Entity\Animaux;
use App\Entity\SessionChasse;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
class SaisieFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('animaux_id', EntityType::class,
['class' => Animaux::class,
'choice_label' => 'id'])
->add('session_chasse_id', EntityType::class,
['class' => SessionChasse::class,])
->add('number_bague', IntegerType::class,
['label' => 'Numéro de bague'])
->add('sexe', TextType::class,)
->add('poids', IntegerType::class,)
->add('save', SubmitType::class,
['label' => 'Enregistrer']);
}
}
I don't give you the another entity because I think if the answer for this one will help to solve the problem with the others. If you need more informations, tell me.
The error that I have is this one :
Expected argument of type "?int", "App\Entity\Animaux" given at property path "animaux_id".
I think it's basic error, but I spend hours on the symfony doc and forums and I don't make any progress.
Thank you for you help.
edit: I add the OneToMany that I forgot at the beginning.

It looks like you do it in the MERISE way, a french method (IMO a good method). As far as I understood, a SessionChasseurAnimaux is connected to one Animal as you were linking to one integer, not a collection. So it's more a OneToOne relation, isn'it? (If not explain us in comment)
You shouldn't link the primary key (animaux_id) but the entity Animal, because Doctrine does the job for you. It will follow the primary key, will hydrate the Animal object then it will associate it to your SessionChasseurAnimaux entity. In other words, SessionChasseurAnimaux->getAnimaux() will return the hydrated animal object, not an id of the animal. So you should replace :
#[ORM\OneToOne(mappedBy: 'id', targetEntity: Animaux::class)]
#[ORM\Column(nullable: true)]
private ?int $animaux = null;
by
#[ORM\OneToOne(mappedBy: 'id', targetEntity: Animaux::class)]
#[ORM\Column(name: "animaux_id", referencedColumnName: "id", nullable: true)]
private ?int $animaux = null;
Then, don't forget to alter the getter and the setter.
public function getAnimaux(): ?Animaux
{
return $this->animaux;
}
public function setAnimaux(?Animaux $animaux_): ChasseurAnimauxSession
{
$this->animaux = $animaux;
return $this;
}
You should have a look on the symfony/maker-bundle. This bundle will help you to create your entities. It generates all the code! If your entities aren't well described, your forms will be very difficult to build. IMO, this tutorial is very good.

First of all, thank you very much for your answer ! I appreciate
I found a solution and I post you the code that work ( But I don't think it's a good way to do the things )
Controller :
class SaisieFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('animaux_id', EntityType::class,
['class' => Animaux::class,
'choice_label' => 'espece'])
->add('session_chasse_id', EntityType::class,
['class' => SessionChasse::class,
'choice_label' => 'date'])
->add('number_bague', IntegerType::class,
['label' => 'Numéro de bague'])
->add('sexe', TextType::class,)
->add('poids', IntegerType::class,)
->add('save', SubmitType::class,
['label' => 'Enregistrer']);
}
}
First Entity ChasseurAniamauxSession :
namespace App\Entity;
use App\Repository\ChasseurAnimauxSessionRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ChasseurAnimauxSessionRepository::class)]
class ChasseurAnimauxSession
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 10, nullable: true)]
private ?string $sexe = null;
#[ORM\Column(nullable: true)]
private ?int $poids = null;
#[ORM\OneToMany(mappedBy: 'id', targetEntity: SessionChasse::class)]
#[ORM\Column(nullable: true)]
private ?SessionChasse $session_chasse_id = null;
#[ORM\OneToMany(mappedBy: 'id', targetEntity: Animaux::class)]
#[ORM\Column(nullable: true)]
private Animaux|null $animaux_id = null;
#[ORM\OneToMany(mappedBy: 'id', targetEntity: User::class)]
#[ORM\Column(nullable: true)]
private ?int $chasseur_id = null;
#[ORM\Column(nullable: true)]
private ?int $number_bague = null;
public function getId(): ?int
{
return $this->id;
}
public function getSexe(): ?string
{
return $this->sexe;
}
public function setSexe(?string $sexe): self
{
$this->sexe = $sexe;
return $this;
}
public function getPoids(): ?int
{
return $this->poids;
}
public function setPoids(?int $poids): self
{
$this->poids = $poids;
return $this;
}
/**
* #return SessionChasse|null
*/
public function getSessionChasseId(): ?SessionChasse
{
return $this->session_chasse_id;
}
/**
* #param SessionChasse|null $session_chasse_id
* #return ChasseurAnimauxSession
*/
public function setSessionChasseId(?SessionChasse $session_chasse_id): ChasseurAnimauxSession
{
$this->session_chasse_id = $session_chasse_id;
return $this;
}
/**
* #return Animaux|null
*/
public function getAnimauxId(): ?Animaux
{
return $this->animaux_id;
}
/**
* #param Animaux $animaux_id
* #return ChasseurAnimauxSession
*/
public function setAnimauxId(Animaux $animaux_id): ChasseurAnimauxSession
{
$this->animaux_id = $animaux_id;
return $this;
}
/**
* #return int|null
*/
public function getChasseurId(): ?int
{
return $this->chasseur_id;
}
/**
* #param int|null $chasseur_id
* #return ChasseurAnimauxSession
*/
public function setChasseurId(?int $chasseur_id): ChasseurAnimauxSession
{
$this->chasseur_id = $chasseur_id;
return $this;
}
public function getNumberBague(): ?int
{
return $this->number_bague;
}
public function setNumberBague(?int $number_bague): self
{
$this->number_bague = $number_bague;
return $this;
}
}
Another Entity Animaux :
namespace App\Entity;
use App\Repository\AnimauxRepository;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: AnimauxRepository::class)]
class Animaux
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $espece = null;
public function __toString(): string
{
return $this->getId();
}
public function getId(): ?int
{
return $this->id;
}
public function getEspece(): ?string
{
return $this->espece;
}
public function setEspece(?string $espece): self
{
$this->espece = $espece;
return $this;
}
}
The type :
class SaisieFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('animaux_id', EntityType::class,
['class' => Animaux::class,
'choice_label' => 'espece'])
->add('session_chasse_id', EntityType::class,
['class' => SessionChasse::class,
'choice_label' => 'date'])
->add('number_bague', IntegerType::class,
['label' => 'Numéro de bague'])
->add('sexe', TextType::class,)
->add('poids', IntegerType::class,)
->add('save', SubmitType::class,
['label' => 'Enregistrer']);
}
}
I'm going to study the links and the answer that Alexandra gave me, it looks really better than what I've done.
If I do something better, I'll post it here
Alexendre, in effet, we learn the Merise way in course ;)
For finish, a ChasseurAnimauxSession can have a lot of animals. I explain :
In this entity, I want to stock for each day of hunt the animals that have been killed by hunters. So I put in this entity the user ( The hunter who killed the animal ), the animal, and the SessionChasse ( Correspond to the day of hunt, a data ) and some informations like the sexe or the weight.

Related

How to return entity object type from EntityType class in form?

Every time I try to send data from form and use doctrine manager I have an error:
As you can see, this problem is according to user_type. I have another entity UserType in which I have this attribute and I want to use it in register form.
I have controller and I want to add all form input into database and then error occurs.
I would like to point out that I don't want to get and set each attribute manually via for instance:
$name = $form['name']->getData();
$userDetails->setName($name);
Because I think that by using entity manager it is supposed to do automatically like this:
UserController.php:
public function register(Request $request){
$user = new User();
$userType = new UserType();
$userDetails = new UserDetails();
$form = $this->createForm(RegisterFormType::class, $user);
$form->handleRequest($request);
if($form->isSubmitted()){
$userDetails = $form->getData();
$em=$this->getDoctrine()->getManager();
$em->persist($userDetails);
$em->flush();
dd($form->getData());
My form in RegisterFormType.php:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
-> add('name',TextType::class,[
'data_class' => UserDetails::class,
'attr' => [
"placeholder" => 'Name'
],
])
-> add('surname',TextType::class,[
'data_class' => UserDetails::class,
'attr' => [
"placeholder" => 'Surname'
],
])
->add('email',TextType::class,[
'attr' => [
"placeholder" => 'Email'
]
])
->add('password',PasswordType::class,[
'attr' => [
"placeholder" => 'Password'
]
])
->add('confirmPassword',PasswordType::class,[
'attr' => [
"placeholder" => 'Confirm Password'
]
])
/* ->add('user_type',ChoiceType::class, [
'help' => 'Do you want to perform? Choose Artist account type. Do you want to employ artist? Choose Firm.',
'label' => "Account type",
'choices' => [
'None' => 0,
'firm' => 1,
'artist' => 2
],
'attr' => [
"class" => 'choice'
]
])*/
->add('user_type',EntityType::class, [
'class' => UserType::class,
'choice_label'=>'type',
/*'choice_label'=>'type',
'choice_value' => function ($entity) {
return $entity ? $entity->getId() : '';
},*/
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
After submitting input in form I get this data:
The problem is user_type sends as a string I suppose, but should as an object. Am I right?
In User.php
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=UserRepository::class)
* #ORM\Table(name="`user`")
*/
class User extends UserDetails
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $email;
/**
* #ORM\Column(type="string", length=255)
*/
private $password;
private $confirmPassword;
/**
* #ORM\OneToOne(targetEntity=UserType::class, cascade={"persist", "remove"})
* #ORM\JoinColumn(nullable=false)
*/
private $user_type;
/**
* #ORM\OneToOne(targetEntity=UserDetails::class, cascade={"persist", "remove"})
* #ORM\JoinColumn(nullable=false)
*/
private $user_details;
/**
* #ORM\OneToMany(targetEntity=UserToOffert::class, mappedBy="user_", orphanRemoval=true)
*/
private $user_to_offert;
/**
* #ORM\OneToMany(targetEntity=Skill::class, mappedBy="user_", orphanRemoval=true)
*/
private $skill;
/**
* #ORM\OneToMany(targetEntity=Requirement::class, mappedBy="user_id", orphanRemoval=true)
*/
private $requirement;
public function __construct()
{
$this->user_to_offert = new ArrayCollection();
$this->skill = new ArrayCollection();
$this->requirement = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getUserType(): ?string
{
return $this->user_type;
}
public function setUserType(string $user_type): self
{
$this->user_type = $user_type;
return $this;
}
public function getUserDetails(): ?UserDetails
{
return $this->user_details;
}
public function setUserDetails(UserDetails $user_details): self
{
$this->user_details = $user_details;
return $this;
}
/**
* #return mixed
*/
public function getConfirmPassword()
{
return $this->confirmPassword;
}
/**
* #param mixed $confirmPassword
*/
public function setConfirmPassword($confirmPassword): void
{
$this->confirmPassword = $confirmPassword;
}
/**
* #return Collection|UserToOffert[]
*/
public function getUserToOffert(): Collection
{
return $this->user_to_offert;
}
public function addUserToOffert(UserToOffert $userToOffert): self
{
if (!$this->user_to_offert->contains($userToOffert)) {
$this->user_to_offert[] = $userToOffert;
$userToOffert->setUser($this);
}
return $this;
}
public function removeUserToOffert(UserToOffert $userToOffert): self
{
if ($this->user_to_offert->removeElement($userToOffert)) {
// set the owning side to null (unless already changed)
if ($userToOffert->getUser() === $this) {
$userToOffert->setUser(null);
}
}
return $this;
}
/**
* #return Collection|Skill[]
*/
public function getSkill(): Collection
{
return $this->skill;
}
public function addSkill(Skill $skill): self
{
if (!$this->skill->contains($skill)) {
$this->skill[] = $skill;
$skill->setUser($this);
}
return $this;
}
public function removeSkill(Skill $skill): self
{
if ($this->skill->removeElement($skill)) {
// set the owning side to null (unless already changed)
if ($skill->getUser() === $this) {
$skill->setUser(null);
}
}
return $this;
}
/**
* #return Collection|Requirement[]
*/
public function getRequirement(): Collection
{
return $this->requirement;
}
public function addRequirement(Requirement $requirement): self
{
if (!$this->requirement->contains($requirement)) {
$this->requirement[] = $requirement;
$requirement->setUser($this);
}
return $this;
}
public function removeRequirement(Requirement $requirement): self
{
if ($this->requirement->removeElement($requirement)) {
// set the owning side to null (unless already changed)
if ($requirement->getUser() === $this) {
$requirement->setUser(null);
}
}
return $this;
}
}
UserDetails.php:
<?php
namespace App\Entity;
use App\Repository\UserDetailsRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* #ORM\Entity(repositoryClass=UserDetailsRepository::class)
*/
class UserDetails
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="IDENTITY")
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
/**
* #ORM\Column(type="string", length=255)
*/
private $surname;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $description;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $photo;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getSurname(): ?string
{
return $this->surname;
}
public function setSurname(string $surname): self
{
$this->surname = $surname;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(?string $description): self
{
$this->description = $description;
return $this;
}
public function getPhoto(): ?string
{
return $this->photo;
}
public function setPhoto(?string $photo): self
{
$this->photo = $photo;
return $this;
}
public function __toString() {
return $this->name;
}
}
In UserType.php:
<?php
namespace App\Entity;
/**
* #ORM\Entity(repositoryClass=UserTypeRepository::class)
*/
class UserType
{
/**
* #ORM\Id
* #ORM\GeneratedValue
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=100)
*/
private $type;
public function getId(): ?int
{
return $this->id;
}
public function getType(): ?string
{
return $this->type;
}
public function setType(string $type): self
{
$this->type = $type;
return $this;
}
public function __toString() {
return $this->type;
}
}
If I remove __toString method I get an error:
Any ideas what am I doing wrong? Thank you for your time in advance. Have a nice day!

Passing parent entity Id into child form

Good day,
I got entity ScheduledCommand into relation OneToMany to ScheduledCommandLimitRange
/**
* #ORM\MappedSuperclass (repositoryClass="Synolia\SyliusSchedulerCommandPlugin\Repository\ScheduledCommandRepository")
* #ORM\Table("scheduled_command")
*/
class ScheduledCommand implements ScheduledCommandInterface
{
/**
* #var int|null
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var string
* #ORM\Column(type="string")
*/
private $name = '';
/**
* #var string
* #ORM\Column(type="string")
*/
private $command = '';
/**
* #var int
* #ORM\Column(type="integer")
*/
private $priority = 0;
/**
* #ORM\OneToMany(targetEntity="ScheduledCommandLimitRange", mappedBy="scheduledCommand", orphanRemoval=true, cascade={"persist"})
* #ORM\JoinColumn(nullable=false)
*/
private $commandLimitRanges;
public function getId(): ?int
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): ScheduledCommandInterface
{
$this->name = $name;
return $this;
}
public function getCommand(): string
{
return $this->command;
}
public function setCommand(string $command): ScheduledCommandInterface
{
$this->command = $command;
return $this;
}
public function getPriority(): int
{
return $this->priority;
}
public function setPriority(int $priority): ScheduledCommandInterface
{
$this->priority = $priority;
return $this;
}
public function getCommandLimitRanges(): ?Collection
{
return $this->commandLimitRanges;
}
public function setCommandLimitRanges(Collection $commandLimitRange): ?Collection
{
$this->commandLimitRanges = $commandLimitRange;
return $this->commandLimitRanges;
}
}
This is my ManyToOne class:
/**
* #ORM\Entity(repositoryClass="Synolia\SyliusSchedulerCommandPlugin\Repository\ScheduledCommandLimitRangeRepository")
* #ORM\Table(name="scheduled_command_limit_range")
*/
class ScheduledCommandLimitRange implements ScheduledCommandLimitRangeInterface
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #var \DateTime|null
* #ORM\Column(type="datetime", nullable=true)
*/
private $timeFrom;
/**
* #var \DateTime|null
* #ORM\Column(type="datetime", nullable=true)
*/
private $timeTo;
/**
* #ORM\ManyToOne(targetEntity="ScheduledCommand", inversedBy="commandLimitRanges")
*/
private $scheduledCommand;
public function getId(): ?int
{
return $this->id;
}
public function getTimeFrom(): ?\DateTime
{
return $this->timeFrom;
}
public function setTimeFrom(?\DateTime $timeFrom): ScheduledCommandLimitRangeInterface
{
$this->timeFrom = $timeFrom;
return $this;
}
public function getTimeTo(): ?\DateTime
{
return $this->timeTo;
}
public function setTimeTo(?\DateTime $timeTo): ScheduledCommandLimitRangeInterface
{
$this->timeTo = $timeTo;
return $this;
}
public function getScheduledCommand(): ?ScheduledCommand
{
return $this->scheduledCommand;
}
public function setScheduledCommand(ScheduledCommand $scheduledCommand): ?ScheduledCommand
{
$this->scheduledCommand = $scheduledCommand;
return $this;
}
I got ScheduledCommandType that is has CollectionType in one field, that has entry_type of CommandLimitType.
final class ScheduledCommandType extends AbstractType
{
/**
* #SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name')
->add('command', CommandChoiceType::class)
->add('arguments')
->add('cronExpression')
->add('commandLimitRanges', CollectionType::class, [
'label' => 'sylius.ui.scheduled_command_limit',
'entry_type' => CommandLimitType::class,
'allow_add' => true,
'allow_delete' => true,
'by_reference' => false,
'inherit_data' => true,
'entry_options' => array(
'scheduledCommand' => 'id'),
])
->add('logFile')
->add('priority')
->add('executeImmediately')
->add('enabled')
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => ScheduledCommand::class,
]);
}
}
This is my entry Type:
class CommandLimitType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('timeTo', DateTimeType::class, [
'widget' => 'single_text',
])
->add('timeFrom', DateTimeType::class, [
'widget' => 'single_text'
])
->add('scheduledCommand', HiddenType::class)
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(['scheduledCommand']);
$resolver->setDefaults([
'data_class' => ScheduledCommandLimitRange::class,
]);
}
}
I had a problem, that when I want to submit this form value CommandLimitRange parentId was null, so i tried to pass into child form parent Id as hidden field. But still got after submit there is stil error:
Cannot read index "0" from object of type "Synolia\SyliusSchedulerCommandPlugin\Entity\ScheduledCommand" because it doesn't implement \ArrayAccess.
What is correct way to pass parent entity Id into entry so that after submit correct parentId is linked to row in db?
Thank you very much
I have found my solution. Okay, so here is few problems, that I did not clearly understand before.
First and foremost - I had only basic setter, instead add / remove method.
public function addCommandLimitRange(ScheduledCommandLimitRange $commandLimitRange): self
{
if (!$this->commandLimitRanges->contains($commandLimitRange)) {
$this->commandLimitRanges[] = $commandLimitRange;
$commandLimitRange->setScheduledCommand($this);
}
return $this;
}
public function removeCommandLimitRange(ScheduledCommandLimitRange $commandLimitRange): self
{
if ($this->commandLimitRanges->removeElement($commandLimitRange)) {
// set the owning side to null (unless already changed)
if ($commandLimitRange->getScheduledCommand() === $this) {
$commandLimitRange->setScheduledCommand(null);
}
}
return $this;
}
Next I needed to make my property an ArrayCollection object in constructor:
public function __construct()
{
$this->commandLimitRanges = new ArrayCollection();
}
And last to get proper delete instead running update with null on parentId I needed to ad orphan_removal option into annotation.
/**
* #ORM\OneToMany(targetEntity="ScheduledCommandLimitRange", mappedBy="scheduledCommand", cascade={"persist"}, orphanRemoval=true)
*/
private $commandLimitRanges;

Symfony Check if at least one of two fields isn't empty on form validation

I've been turning this around in my head for quite a while now and still wasn't able to find a solution to my problem. Using Symfony 4 forms and constraints I'm unable to setup a check to say that at least one of two fields must not be empty when submitting form that contains a sub-form.
I have a Booking entity which contains a Visitor entity which has a phoneNumber property and a email property. I'd like to be able to create a Booking which has a "visitors" CollectionType (where I'm allowed to add visitors from the BookingType form).
My BookingType form (a bit simplified):
class BookingType extends AbstractType
{
private $router;
private $translator;
public function __construct(UrlGeneratorInterface $router, TranslatorInterface $translator)
{
$this->router = $router;
$this->translator = $translator;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('bookableTimeSlot', EntityType::class, [
'label' => 'entity.booking.bookable-time-slot',
'class' => BookableTimeSlot::class,
'choice_label' => function ($bookableTimeSlot) {
return $bookableTimeSlot->getStartDateTime()->format('d.m.Y h\hi');
}
])
->add('visitors', CollectionType::class, [
'entry_type' => VisitorType::class,
'label' => 'entity.booking.visitors',
'allow_add' => true,
'by_reference' => false,
'entry_options' => ['label' => false]
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Booking::class,
'user' => User::class,
]);
}
}
My Visitor entity (a bit simplified):
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Context\ExecutionContextInterface;
/**
* #ORM\Entity(repositoryClass="App\Repository\VisitorRepository")
*/
class Visitor
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $firstName;
/**
* #ORM\Column(type="string", length=255)
*/
private $lastName;
/**
* #ORM\Column(type="string", length=45, nullable=true)
*/
private $phone;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Booking", inversedBy="visitors")
* #ORM\JoinColumn(nullable=false)
*/
private $booking;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $email;
public function getId(): ?int
{
return $this->id;
}
public function getFirstName(): ?string
{
return $this->firstName;
}
public function setFirstName(string $firstName): self
{
$this->firstName = $firstName;
return $this;
}
public function getLastName(): ?string
{
return $this->lastName;
}
public function setLastName(string $lastName): self
{
$this->lastName = $lastName;
return $this;
}
public function getPhone(): ?string
{
return $this->phone;
}
public function setPhone(string $phone): self
{
$this->phone = $phone;
return $this;
}
public function getBooking(): ?Booking
{
return $this->booking;
}
public function setBooking(?Booking $booking): self
{
$this->booking = $booking;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(?string $email): self
{
$this->email = $email;
return $this;
}
}
And finaly my VisitorType form (a bit simplified):
class VisitorType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstName', TextType::class, [
'label' => 'entity.visitor.first-name',
])
->add('lastName', TextType::class, [
'label' => 'entity.visitor.last-name',
])
->add('phone', TextType::class, [
'label' => 'entity.visitor.phone-number',
'required' => false,
])
->add('email', TextType::class, [
'label' => 'entity.visitor.email',
'required' => false,
'constraints' => [
new Email()
]
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Visitor::class,
]);
}
}
I've tried to add an Expression constraint to the email and phone field which looked something like this:
new Expression([
'expression' => 'this.getPhone() == null && this.getEmail() == null'
])
Also tried to add constraint directly to the entity, but nothing seems to work correctly for me.
Any help would be greatly appreciated.
UPDATE
I haven't specified this, but my problem comes from the fact that I would like to validate the VisitorType form from another form which adds the VisitorType as a CollectionType.
try with callback
/**
* #Assert\Callback
*/
public function validate(ExecutionContextInterface $context, $payload)
{
if (null === $this->getEmail() && null === $this->getPhone())
$context->buildViolation('Your message here.')
->atPath('email')
->addViolation();
// you can add onther "if" if you like
}

How to save One To Many relations in Sonata?

I'm facing a problem in Symfony4 and Sonata Admin.
I have 3 entities : Orders, Product and Orders Product.
Here they are :
Orders :
class Orders
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="datetime")
*/
private $dateAdd;
/**
* #ORM\Column(type="datetime")
*/
private $dateUpd;
/**
* #ORM\Column(type="date")
*/
private $deliveryDate;
/**
* #ORM\Column(type="string", length=255)
*/
private $internalReference;
/**
* #ORM\Column(type="string", length=255)
*/
private $deliveryContactName;
/**
* #ORM\Column(type="string", length=15)
*/
private $deliveryContactPhone;
/**
* #ORM\Column(type="string", length=255)
*/
private $deliveryAddress1;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $deliveryAddress2;
/**
* #ORM\Column(type="string", length=10)
*/
private $deliveryPostalCode;
/**
* #ORM\Column(type="string", length=255)
*/
private $deliveryCountry;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $deliveryCompany;
/**
* #ORM\Column(type="integer")
*/
private $status;
/**
* #ORM\Column(type="text", nullable=true)
*/
private $comment;
/**
* #ORM\Column(type="string", length=255)
*/
private $deliveryCity;
/**
* #ORM\OneToMany(targetEntity="App\Entity\OrdersProduct", mappedBy="orders")
*/
private $product;
public function __construct()
{
$this->product = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getDateAdd(): ?\DateTimeInterface
{
return $this->dateAdd;
}
public function setDateAdd(\DateTimeInterface $dateAdd): self
{
$this->dateAdd = $dateAdd;
return $this;
}
public function getDateUpd(): ?\DateTimeInterface
{
return $this->dateUpd;
}
public function setDateUpd(\DateTimeInterface $dateUpd): self
{
$this->dateUpd = $dateUpd;
return $this;
}
public function getDeliveryDate(): ?\DateTimeInterface
{
return $this->deliveryDate;
}
public function setDeliveryDate(\DateTimeInterface $deliveryDate): self
{
$this->deliveryDate = $deliveryDate;
return $this;
}
public function getInternalReference(): ?string
{
return $this->internalReference;
}
public function setInternalReference(?string $internalReference): self
{
$this->internalReference = $internalReference;
return $this;
}
public function getDeliveryContactName(): ?string
{
return $this->deliveryContactName;
}
public function setDeliveryContactName(string $deliveryContactName): self
{
$this->deliveryContactName = $deliveryContactName;
return $this;
}
public function getDeliveryContactPhone(): ?string
{
return $this->deliveryContactPhone;
}
public function setDeliveryContactPhone(string $deliveryContactPhone): self
{
$this->deliveryContactPhone = $deliveryContactPhone;
return $this;
}
public function getDeliveryAddress1(): ?string
{
return $this->deliveryAddress1;
}
public function setDeliveryAddress1(string $deliveryAddress1): self
{
$this->deliveryAddress1 = $deliveryAddress1;
return $this;
}
public function getDeliveryAddress2(): ?string
{
return $this->deliveryAddress2;
}
public function setDeliveryAddress2(?string $deliveryAddress2): self
{
$this->deliveryAddress2 = $deliveryAddress2;
return $this;
}
public function getDeliveryPostalCode(): ?string
{
return $this->deliveryPostalCode;
}
public function setDeliveryPostalCode(string $deliveryPostalCode): self
{
$this->deliveryPostalCode = $deliveryPostalCode;
return $this;
}
public function getDeliveryCountry(): ?string
{
return $this->deliveryCountry;
}
public function setDeliveryCountry(string $deliveryCountry): self
{
$this->deliveryCountry = $deliveryCountry;
return $this;
}
public function getDeliveryCompany(): ?string
{
return $this->deliveryCompany;
}
public function setDeliveryCompany(?string $deliveryCompany): self
{
$this->deliveryCompany = $deliveryCompany;
return $this;
}
public function getStatus(): ?int
{
return $this->status;
}
public function setStatus(int $status): self
{
$this->status = $status;
return $this;
}
public function getComment(): ?string
{
return $this->comment;
}
public function setComment(?string $comment): self
{
$this->comment = $comment;
return $this;
}
public function getDeliveryCity(): ?string
{
return $this->deliveryCity;
}
public function setDeliveryCity(string $deliveryCity): self
{
$this->deliveryCity = $deliveryCity;
return $this;
}
public function __toString()
{
if ($this->id)
return $this->id." -".$this->internalReference;
else
return "";
}
/**
* #return Collection|OrdersProduct[]
*/
public function getProduct(): Collection
{
return $this->product;
}
public function addProduct(OrdersProduct $product): self
{
if (!$this->product->contains($product)) {
$this->product[] = $product;
$product->setOrders($this);
}
return $this;
}
public function removeProduct(OrdersProduct $product): self
{
if ($this->product->contains($product)) {
$this->product->removeElement($product);
// set the owning side to null (unless already changed)
if ($product->getOrders() === $this) {
$product->setOrders(null);
}
}
return $this;
}
}
Product :
class Product
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="string", length=255)
*/
private $name;
/**
* #ORM\Column(type="float")
*/
private $priceWT;
/**
* #ORM\Column(type="float")
*/
private $vat;
/**
* #ORM\Column(type="datetime")
*/
private $dateAdd;
/**
* #ORM\Column(type="datetime")
*/
private $dateUpd;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Category", inversedBy="products")
* #ORM\JoinColumn(nullable=false)
*/
private $category;
/**
* #ORM\Column(type="boolean")
*/
private $isDeleted;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getPriceWT(): ?float
{
return $this->priceWT;
}
public function setPriceWT(float $priceWT): self
{
$this->priceWT = $priceWT;
return $this;
}
public function getVat(): ?float
{
return $this->vat;
}
public function setVat(float $vat): self
{
$this->vat = $vat;
return $this;
}
public function getDateAdd(): ?\DateTimeInterface
{
return $this->dateAdd;
}
public function setDateAdd(\DateTimeInterface $dateAdd): self
{
$this->dateAdd = $dateAdd;
return $this;
}
public function getDateUpd(): ?\DateTimeInterface
{
return $this->dateUpd;
}
public function setDateUpd(\DateTimeInterface $dateUpd): self
{
$this->dateUpd = $dateUpd;
return $this;
}
public function getCategory(): ?Category
{
return $this->category;
}
public function setCategory(?Category $category): self
{
$this->category = $category;
return $this;
}
public function getIsDeleted(): ?bool
{
return $this->isDeleted;
}
public function setIsDeleted(bool $isDeleted): self
{
$this->isDeleted = $isDeleted;
return $this;
}
public function __toString()
{
if ($this->name)
return $this->name;
else
return "Nouveau Produit";
}
public function calculatePriceTI()
{
return $this->priceWT * (1 + $this->vat);
}
}
OrdersProduct :
class OrdersProduct
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Orders", inversedBy="product")
* #ORM\JoinColumn(nullable=false)
*/
private $orders;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Product")
* #ORM\JoinColumn(nullable=false)
*/
private $product;
/**
* #ORM\Column(type="integer")
*/
private $quantity;
/**
* #ORM\Column(type="float")
*/
private $priceWT;
public function getId(): ?int
{
return $this->id;
}
public function getOrders(): ?Orders
{
return $this->orders;
}
public function setOrders(?Orders $orders): self
{
$this->orders = $orders;
return $this;
}
public function getProduct(): ?Product
{
return $this->product;
}
public function setProduct(?Product $product): self
{
$this->product = $product;
return $this;
}
public function getQuantity(): ?int
{
return $this->quantity;
}
public function setQuantity(int $quantity): self
{
$this->quantity = $quantity;
return $this;
}
public function getPriceWT(): ?float
{
return $this->priceWT;
}
public function setPriceWT(float $priceWT): self
{
$this->priceWT = $priceWT;
return $this;
}
public function __toString()
{
if($this->id)
return $this->getOrders()->getId()." - ".$this->getProduct()->getName();
else
return "";
}
}
And here is the Orders Admin :
class OrdersAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->with('label.orders.group1', [
'class' => 'col-md-6'
])
->add('internalReference', TextType::class, [
'label' => 'label.orders.internalReference',
'required' => true
])
->add('deliveryDate', DateType::class, [
'label' => 'label.orders.deliveryDate'
])
->add('comment', TextareaType::class, [
'label' => 'label.orders.comment',
'required' => false
])
->add('deliveryContactName', TextType::class, [
'label' => 'label.orders.deliveryContactName'
])
->add('deliveryContactPhone', TextType::class, [
'label' => 'label.orders.deliveryContactPhone'
])
->add('status', ChoiceType::class, [
'label' => 'label.orders.status',
'choices' => array(
'label.orders.statuses.pending' => 1,
'label.orders.statuses.confirmed' => 2,
'label.orders.statuses.sent' => 3,
'label.orders.statuses.cancel' => 4,
)
])
->end();
$formMapper->with('label.orders.group2', [
'class' => 'col-md-6'
])
->add('deliveryCompany', TextType::class, [
'label' => 'label.orders.deliveryCompany',
'required' => false
])
->add('deliveryAddress1', TextType::class, [
'label' => 'label.orders.deliveryAddress1'
])
->add('deliveryAddress2', TextType::class, [
'label' => 'label.orders.deliveryAddress2',
'required' => false
])
->add('deliveryPostalCode', TextType::class, [
'label' => 'label.orders.deliveryPostalCode'
])
->add('deliveryCity', TextType::class, [
'label' => 'label.orders.deliveryCity'
])
->add('deliveryCountry', TextType::class, [
'label' => 'label.orders.deliveryCountry'
])
->end();
if ($this->isCurrentRoute('edit', 'admin.orders'))
$formMapper->add('product', OrdersProductType::class, array(
'order' => $this->getSubject(),
)
);
}
protected function configureDatagridFilters(DatagridMapper $filter)
{
$filter->add('internalReference')
->add('deliveryCompany');
}
protected function configureListFields(ListMapper $list)
{
$list->addIdentifier('id');
$list->add('dateAdd', 'date', [
'label' => 'label.orders.dateAdd'
]);
}
public function prePersist($orders)
{
$orders->setdateAdd(new \DateTime());
$orders->setDateUpd(new \DateTime());
}
public function preUpdate($orders)
{
$orders->setDateUpd(new \DateTime());
}
}
And the OrdersProductType :
class OrdersProductType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('product', EntityType::class, array(
'class' => Product::class,
'multiple' => false,
'expanded' => false,
))
->add('quantity')
->add('priceWT')
->add('orders', HiddenType::class, array(
'data' => $options['order']
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setRequired(array('order'));
}
}
I tried to use a CollectionType::class with a OrdersProductAdmin, but It is impossible to save the OrdersProduct as I don't know how to pass the Orders id to the embedded form. So, I made a custom form type, but :
When I submit the form, I get the error :
Expected value of type "App\Entity\OrdersProduct" for association field "App\Entity\Orders#$product", got "Proxies\__CG__\App\Entity\Product" instead.
If I dump the $orders var in the preupdate function, I have :
OrdersAdmin.php on line 121:
OrdersProduct {#1405 ▶}
OrdersAdmin.php on line 121:
OrdersProduct {#1419 ▶}
OrdersAdmin.php on line 121:
Product {#1420 ▶}
OrdersAdmin.php on line 121:
"33"
OrdersAdmin.php on line 121:
"12"
OrdersAdmin.php on line 121:
"1 -SG-000251 wonder"
The first 2 OrdersProduct are correct (they are in my DB). But the last 4 items are just not correct ! It should be OrdersProduct, with a Product, a quantity, a price and an order.
Thanks for your help.
Best
I found the (partial, as I have a form issue now !) solution !
Here are the code :
Orders Class :
/**
* #ORM\Entity(repositoryClass="App\Repository\OrdersRepository")
*/
class Orders
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\Column(type="datetime")
*/
private $dateAdd;
/**
* #ORM\Column(type="datetime")
*/
private $dateUpd;
/**
* #ORM\Column(type="date")
*/
private $deliveryDate;
/**
* #ORM\Column(type="string", length=255)
*/
private $internalReference;
/**
* #ORM\Column(type="string", length=255)
*/
private $deliveryContactName;
/**
* #ORM\Column(type="string", length=15)
*/
private $deliveryContactPhone;
/**
* #ORM\Column(type="string", length=255)
*/
private $deliveryAddress1;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $deliveryAddress2;
/**
* #ORM\Column(type="string", length=10)
*/
private $deliveryPostalCode;
/**
* #ORM\Column(type="string", length=255)
*/
private $deliveryCountry;
/**
* #ORM\Column(type="string", length=255, nullable=true)
*/
private $deliveryCompany;
/**
* #ORM\Column(type="integer")
*/
private $status;
/**
* #ORM\Column(type="text", nullable=true)
*/
private $comment;
/**
* #ORM\Column(type="string", length=255)
*/
private $deliveryCity;
/**
* #ORM\OneToMany(targetEntity="App\Entity\OrdersProduct", cascade={"persist"}, mappedBy="orders")
*/
private $product;
public function __construct()
{
$this->product = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getDateAdd(): ?\DateTimeInterface
{
return $this->dateAdd;
}
public function setDateAdd(\DateTimeInterface $dateAdd): self
{
$this->dateAdd = $dateAdd;
return $this;
}
public function getDateUpd(): ?\DateTimeInterface
{
return $this->dateUpd;
}
public function setDateUpd(\DateTimeInterface $dateUpd): self
{
$this->dateUpd = $dateUpd;
return $this;
}
public function getDeliveryDate(): ?\DateTimeInterface
{
return $this->deliveryDate;
}
public function setDeliveryDate(\DateTimeInterface $deliveryDate): self
{
$this->deliveryDate = $deliveryDate;
return $this;
}
public function getInternalReference(): ?string
{
return $this->internalReference;
}
public function setInternalReference(?string $internalReference): self
{
$this->internalReference = $internalReference;
return $this;
}
public function getDeliveryContactName(): ?string
{
return $this->deliveryContactName;
}
public function setDeliveryContactName(string $deliveryContactName): self
{
$this->deliveryContactName = $deliveryContactName;
return $this;
}
public function getDeliveryContactPhone(): ?string
{
return $this->deliveryContactPhone;
}
public function setDeliveryContactPhone(string $deliveryContactPhone): self
{
$this->deliveryContactPhone = $deliveryContactPhone;
return $this;
}
public function getDeliveryAddress1(): ?string
{
return $this->deliveryAddress1;
}
public function setDeliveryAddress1(string $deliveryAddress1): self
{
$this->deliveryAddress1 = $deliveryAddress1;
return $this;
}
public function getDeliveryAddress2(): ?string
{
return $this->deliveryAddress2;
}
public function setDeliveryAddress2(?string $deliveryAddress2): self
{
$this->deliveryAddress2 = $deliveryAddress2;
return $this;
}
public function getDeliveryPostalCode(): ?string
{
return $this->deliveryPostalCode;
}
public function setDeliveryPostalCode(string $deliveryPostalCode): self
{
$this->deliveryPostalCode = $deliveryPostalCode;
return $this;
}
public function getDeliveryCountry(): ?string
{
return $this->deliveryCountry;
}
public function setDeliveryCountry(string $deliveryCountry): self
{
$this->deliveryCountry = $deliveryCountry;
return $this;
}
public function getDeliveryCompany(): ?string
{
return $this->deliveryCompany;
}
public function setDeliveryCompany(?string $deliveryCompany): self
{
$this->deliveryCompany = $deliveryCompany;
return $this;
}
public function getStatus(): ?int
{
return $this->status;
}
public function setStatus(int $status): self
{
$this->status = $status;
return $this;
}
public function getComment(): ?string
{
return $this->comment;
}
public function setComment(?string $comment): self
{
$this->comment = $comment;
return $this;
}
public function getDeliveryCity(): ?string
{
return $this->deliveryCity;
}
public function setDeliveryCity(string $deliveryCity): self
{
$this->deliveryCity = $deliveryCity;
return $this;
}
public function __toString()
{
if ($this->id)
return $this->id." -".$this->internalReference;
else
return "";
}
/**
* #return Collection|OrdersProduct[]
*/
public function getProduct(): Collection
{
return $this->product;
}
public function addProduct(OrdersProduct $product): self
{
if (!$this->product->contains($product)) {
$this->product[] = $product;
$product->setOrders($this);
}
return $this;
}
public function removeProduct(OrdersProduct $product): self
{
if ($this->product->contains($product)) {
$this->product->removeElement($product);
// set the owning side to null (unless already changed)
if ($product->getOrders() === $this) {
$product->setOrders(null);
}
}
return $this;
}
public function setProduct($products)
{
$this->product = $products;
foreach ($products as $product)
{
$product->setOrders($this);
}
}
}
OrdersProduct Class :
/**
* #ORM\Entity(repositoryClass="App\Repository\OrdersProductRepository")
*/
class OrdersProduct
{
/**
* #ORM\Id()
* #ORM\GeneratedValue()
* #ORM\Column(type="integer")
*/
private $id;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Orders", inversedBy="product")
* #ORM\JoinColumn(nullable=false)
*/
private $orders;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Product")
* #ORM\JoinColumn(nullable=false)
*/
private $product;
/**
* #ORM\Column(type="integer")
*/
private $quantity;
/**
* #ORM\Column(type="float")
*/
private $priceWT;
public function getId(): ?int
{
return $this->id;
}
public function getOrders(): ?Orders
{
return $this->orders;
}
public function setOrders(?Orders $orders): self
{
$this->orders = $orders;
return $this;
}
public function getProduct(): ?Product
{
return $this->product;
}
public function setProduct(?Product $product): self
{
$this->product = $product;
return $this;
}
public function getQuantity(): ?int
{
return $this->quantity;
}
public function setQuantity(int $quantity): self
{
$this->quantity = $quantity;
return $this;
}
public function getPriceWT(): ?float
{
return $this->priceWT;
}
public function setPriceWT(float $priceWT): self
{
$this->priceWT = $priceWT;
return $this;
}
public function __toString()
{
if($this->id)
return $this->getOrders()->getId()." - ".$this->getProduct()->getName();
else
return "";
}
}
OrdersAdmin :
class OrdersAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->with('label.orders.group1', [
'class' => 'col-md-6'
])
->add('internalReference', TextType::class, [
'label' => 'label.orders.internalReference',
'required' => true
])
->add('deliveryDate', DateType::class, [
'label' => 'label.orders.deliveryDate'
])
->add('comment', TextareaType::class, [
'label' => 'label.orders.comment',
'required' => false
])
->add('deliveryContactName', TextType::class, [
'label' => 'label.orders.deliveryContactName'
])
->add('deliveryContactPhone', TextType::class, [
'label' => 'label.orders.deliveryContactPhone'
])
->add('status', ChoiceType::class, [
'label' => 'label.orders.status',
'choices' => array(
'label.orders.statuses.pending' => 1,
'label.orders.statuses.confirmed' => 2,
'label.orders.statuses.sent' => 3,
'label.orders.statuses.cancel' => 4,
)
])
->end();
$formMapper->with('label.orders.group2', [
'class' => 'col-md-6'
])
->add('deliveryCompany', TextType::class, [
'label' => 'label.orders.deliveryCompany',
'required' => false
])
->add('deliveryAddress1', TextType::class, [
'label' => 'label.orders.deliveryAddress1'
])
->add('deliveryAddress2', TextType::class, [
'label' => 'label.orders.deliveryAddress2',
'required' => false
])
->add('deliveryPostalCode', TextType::class, [
'label' => 'label.orders.deliveryPostalCode'
])
->add('deliveryCity', TextType::class, [
'label' => 'label.orders.deliveryCity'
])
->add('deliveryCountry', TextType::class, [
'label' => 'label.orders.deliveryCountry'
])
->end();
if ($this->isCurrentRoute('edit', 'admin.orders'))
$formMapper->add('product', CollectionType::class, array(
'by_reference' => false,
),
array(
'edit' => 'inline',
'inline' => 'inline'
));
}
protected function configureDatagridFilters(DatagridMapper $filter)
{
$filter->add('internalReference')
->add('deliveryCompany');
}
protected function configureListFields(ListMapper $list)
{
$list->addIdentifier('id');
$list->add('dateAdd', 'date', [
'label' => 'label.orders.dateAdd'
]);
}
public function prePersist($orders)
{
$orders->setdateAdd(new \DateTime());
$orders->setDateUpd(new \DateTime());
}
public function preUpdate($orders)
{
$orders->setDateUpd(new \DateTime());
$orders->setProduct($orders->getProduct());
}
}
OrdersProductAdmin :
class OrdersProductAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('product', EntityType::class, [
'class'=> 'App\Entity\Product',
'choice_label' => 'name'
])
->add('quantity')
->add('priceWT')
->add('orders', EntityType::class, [
'class' => Orders::class,
'data' => $this->getRoot()->getSubject()
]);
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
}
protected function configureListFields(ListMapper $listMapper)
{
}
public function prePersist($objects)
{
//$objects->setOrders($this->getRoot()->getSubject());
//dd($objects);
}
The OrdersProduct form is well displayed (embedded in the other form). I can get the Orders->id in the OrdersProduct Form.
Now, I have another issue : the form doesn't refresh throwing an error 500 !

Call to a member function getRepository() on a non-object

I am new In symfony2 with mongoDB, I am creating one relationship with document relation using ODM. I facing above issue when I creating form type, My file code as below
File path: /src/AppBundle/Form/Type/ProductFormType.php
<?php
namespace AppBundle\Form\Type;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
class ProductFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('name', 'text', array('label' => 'Product Name'))
->add('description', 'textarea',array('label' => 'Description'))
->add('Category', 'document', array(
'label'=>'Product Category',
'class' => 'AppBundle:Category',
'property' => 'name',
))
->add('save', 'submit');
}
public function getName()
{
return 'product';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Document\Product'
));
}
}
?>
File: src/AppBundle/Document/product.php
<?php
namespace AppBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Symfony\Component\Validator\Constraints as Assert;
/** #ODM\Document */
class Product
{
/** #ODM\Id */
private $id;
/** #ODM\String */
protected $name;
/** #ODM\String */
protected $description;
/** #ODM\ReferenceOne(targetDocument="Category", cascade="all") */
private $Category;
public function getId() { return $this->id; }
public function getName() { return $this->name; }
public function setName($name) { $this->name = $name; }
/**
* Set category
*
* #param AppBundle\Document\Category $category
* #return self
*/
public function setCategory(\AppBundle\Document\Category $category)
{
$this->Category = $category;
return $this;
}
/**
* Get category
*
* #return AppBundle\Document\Category $category
*/
public function getCategory()
{
return $this->Category;
}
public function getDescription() { return $this->description; }
public function setDescription($description) { $this->description = $description; }
}
File src/Appbundle/Docment/Category.php
<?php
namespace AppBundle\Document;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
//** #ODM\Document */
class Category
{
/** #ODM\Id */
protected $id;
/** #ODM\String */
protected $cat_id;
/** #ODM\String */
protected $categoryname;
/** #ReferenceMany(targetDocument="Product" mappedBy="category") */
private $products;
public function __construct()
{
$this->products = new ArrayCollection();
}
/**
* Add product
*
* #param \AppBundle\Document\Product $product
*
* #return Category
*/
public function addProduct(\AppBundle\Document\Product $product)
{
$this->products[] = $product;
return $this;
}
/**
* Remove product
*
* #param \AppBundle\Document\Product $product
*/
public function removeProduct(\AppBundle\Document\Product $product)
{
$this->products->removeElement($product);
}
/**
* Get products
*
* #return \Doctrine\Common\Collections\Collection
*/
public function getProducts()
{
return $this->products;
}
public function getId()
{
return $this->id;
}
public function getCat_id() { return $this->cat_id; }
public function setCat_id($cat_id) { $this->cat_id = $cat_id; }
public function getDescription() { return $this->categoryname; }
public function setDescription($categoryname) { $this->categoryname = $categoryname; }
}
I also tried Following process :
getter-setter for MongoDB
php app/console doctrine:mongodb:generate:documents AppBundle
Then clear cache and set developer enviroment
can anybody have a solutions, Please help me.
Thanks in Advance