I made a form in order to create events. First, the user has to create a profile and be connected. He has a list of his own addresses. Currently, in the form he can select any addresses, even those created by other users. I would like to allow him to see only addresses he has created in drop selection.
In EventType file, I used
EntityType::class
for Location entity, knowing that thanks to it addresses are created.In Entity file for Location, the column 'organizer' is created in order to know who created the address. It's connected with a ManyToOne to User class.
Where do I have to specify that user must select only his own address in the form ?
EventType.php
<?php
namespace App\Form;
use App\Entity\Event;
use App\Entity\Language;
use App\Entity\Location;
use App\Entity\Category;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\TimeType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
class EventType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('title')
->add('description', TextareaType::class)
->add('spokenlanguage', EntityType::class, [
'class' => Language::class,
'choice_label' => 'name',
'placeholder' => 'Je sélectionne une langue étrangère',
])
->add('category', EntityType::class, [
'class' => Category::class,
'choice_label' => 'title',
'placeholder' => 'Je sélectionne un type de sortie ou d\'activité',
])
->add('start', DateTimeType::class, [
'widget' => 'choice'
])
->add('end', TimeType::class, [
'input' => 'datetime',
'widget' => 'choice',
])
->add('address', EntityType::class, [
'class' => Location::class,
'choice_label' => 'address',
'placeholder' => 'Je sélectionne une adresse',
])
->add('save', SubmitType::class, [
'attr' => ['class' => 'save'],
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Event::class,
'translation_domain' => 'forms'
]);
}
}
Location.php
<?php
namespace App\Entity;
use App\Repository\LocationRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: LocationRepository::class)]
class Location
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $name = null;
#[ORM\Column(length: 255)]
private ?string $number = null;
#[ORM\Column(length: 255)]
private ?string $street = null;
#[ORM\Column(length: 255)]
private ?string $zipcode = null;
#[ORM\Column(length: 255)]
private ?string $city = null;
#[ORM\ManyToOne(inversedBy: 'locations')]
private ?BigCity $bigcity = null;
#[ORM\OneToMany(mappedBy: 'address', targetEntity: Event::class)]
private Collection $events;
#[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 7, nullable: true)]
private ?string $lat = null;
#[ORM\Column(type: Types::DECIMAL, precision: 10, scale: 7, nullable: true)]
private ?string $lon = null;
#[ORM\ManyToOne(inversedBy: 'locations')]
private ?User $organizer = null;
public function __construct()
{
$this->events = new ArrayCollection();
}
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 getNameAndId(): ?string
{
$nameandid =$this->getName() . ' (Id : ' . $this->getId() . ')';
return $nameandid;
}
public function getNumber(): ?string
{
return $this->number;
}
public function setNumber(string $number): self
{
$this->number = $number;
return $this;
}
public function getStreet(): ?string
{
return $this->street;
}
public function setStreet(string $street): self
{
$this->street = $street;
return $this;
}
public function getZipcode(): ?string
{
return $this->zipcode;
}
public function setZipcode(string $zipcode): self
{
$this->zipcode = $zipcode;
return $this;
}
public function getCity(): ?string
{
return $this->city;
}
public function setCity(string $city): self
{
$this->city = $city;
return $this;
}
public function getAddress(): ?string
{
$address =$this->getName() . ', ' . $this->getNumber() . ' ' . $this->getStreet() . ', ' . $this->getCity();
return $address;
}
public function getBigcity(): ?BigCity
{
return $this->bigcity;
}
public function setBigcity(?BigCity $bigcity): self
{
$this->bigcity = $bigcity;
return $this;
}
/**
* @return Collection<int, Event>
*/
public function getEvents(): Collection
{
return $this->events;
}
public function addEvent(Event $event): self
{
if (!$this->events->contains($event)) {
$this->events->add($event);
$event->setAddress($this);
}
return $this;
}
public function removeEvent(Event $event): self
{
if ($this->events->removeElement($event)) {
// set the owning side to null (unless already changed)
if ($event->getAddress() === $this) {
$event->setAddress(null);
}
}
return $this;
}
public function getLat(): ?string
{
return $this->lat;
}
public function setLat(?string $lat): self
{
$this->lat = $lat;
return $this;
}
public function getLon(): ?string
{
return $this->lon;
}
public function setLon(?string $lon): self
{
$this->lon = $lon;
return $this;
}
public function getOrganizer(): ?User
{
return $this->organizer;
}
public function setOrganizer(?User $organizer): self
{
$this->organizer = $organizer;
return $this;
}
}
CodePudding user response:
Here is the solution :
Type.php file
$user = $options['user'];
$builder
->add('address', EntityType::class, [
'class' => Location::class,
'query_builder' => function (EntityRepository $er) use ($user) {
return $er
->createQueryBuilder('l')
->andWhere('l.organizer = :user')
->setParameter('user', $user);
},
'choice_label' => 'address',
'placeholder' => 'Je sélectionne une adresse',
])
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Event::class,
'user' => User::class
]);
}
Specify user in Controller.php
$form = $this->createForm(EventType::class, $event, ['user' => $user]);
CodePudding user response:
this is possible in different ways
Option 1 a filtered options list from the EventController.php
$form = $this->createForm(EventType::class, $event, [
'addresses' => $locationRepository->findBy(['organizer' => $user])
]);
More information https://symfony.com/doc/current/forms.html#passing-options-to-forms
and in EventType.php the choice list within the EntityType
->add('address', EntityType::class, [
'class' => Location::class,
'choice_label' => 'address',
'choices' => $options['addresses'],
])
More information https://symfony.com/doc/current/reference/forms/types/entity.html#choices
Option 2 the transfer of the user, as already described above by yourself
EventController.php
$form = $this->createForm(EventType::class, $event, ['user' => $user]);
and build the query with the query_builder option
EventType.php
$user = $options['user'];
$builder
...
->add('address', EntityType::class, [
...
'query_builder' => function (EntityRepository $er) use ($user) {
$qb = $er->createQueryBuilder('l');
return $er
->andWhere(
$qb->expr()->eq('l.user', ':user')
)
->setParameter('user', $user)
;
},
])
...
;