I'm here because I can't find a solution to my problem. I have a form in Symfony 6 and one of the value is id_client and reffer to another entity, Client (relation ManyToOne).
I tested few methods to make the field be a select choice of all the clients (I show the name of the client). And every of them works but when I submit the form this value is add as the whole entity and not just the id. This is a problem because I end with this:
Expected argument of type "int", "App\\Entity\\Client" given at property path "id_client".
In my form it looks like this:
<?php
namespace App\Form;
use App\Entity\Client;
use App\Entity\Group;
use App\Repository\ClientRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
class Group1Type extends AbstractType
{
private $clientRepository;
public function __construct(ClientRepository $clientRepository)
{
$this->clientRepository = $clientRepository;
$this->clients = $clientRepository->findAll();
}
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name', TextType::class, [
'attr' => [
'class' => 'form-control'
],
'label' => 'Name: '
])
->add('can_display', CheckboxType::class, [
'label' => 'Can display : ',
'attr' => [
'class' => 'my-3 mx-2'
]
])
->add('id_client', EntityType::class, [
'class' => Client::class,
// 'choices' => $this->clientRepository->findAllNameAlphabetical(),
// 'query_builder' => function (ClientRepository $client) {
// return $client->findAllNameAlphabetical();
// },
'choice_label' => 'name',
'expanded' => false,
'multiple' => false,
'attr' => [
'class' => 'form-control'
]
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => Group::class,
]);
}
}
The twig:
<section class="container my-3">
<div class="row">
<div class="col">
{{ form_start(form) }}
{{ form_row(form.name) }}
{{ form_row(form.can_display) }}
{{ form_row(form.id_client) }}
<button class="btn btn-primary my-3">{{ button_label|default('Save') }}</button>
{{ form_end(form) }}
</div>
</div>
</section>
The controller (I have the same result if I let it as it was at the beginning):
#[Route('/new', name: 'app_group_new', methods: ['GET', 'POST'])]
public function new(Request $request, GroupRepository $groupRepository): Response
{
$group = new Group();
$form = $this->createForm(Group1Type::class, $group);
$form->handleRequest($request);
// $group->id_client = $group->id_client->id;
if ($form->isSubmitted()) {
// dd('submit');
// if(gettype($group->id_client)=="Client"){
// dd($group);
if($form->isValid()){
dd('valid');
$groupRepository->save($group, true);
$this->addFlash('success', 'The creation went successfully.');
return $this->redirectToRoute('app_group_index', [], Response::HTTP_SEE_OTHER);
// }
}
}
return $this->renderForm('group/new.html.twig', [
'group' => $group,
'form' => $form,
]);
}
My entity:
#[ORM\Column]
private ?int $id_client = null;
In your entity, do not name properties with id_*
. The client-Property in the Group(?) Entity should be named $client
, not $id_client
.
Then, in your Form, name that field excactly like the property in the Group-Entity. Doctrine (as a DBAL should do) does that behind-the-scene relating of the object by the actual id for you.
Group1Type.php
->add('client', EntityType::class, [
'class' => Client::class,
// ...
])
And your Group-Entity (or Group1?)
class Group
{
// ...
#[ORM\ManyToOne(targetEntity: Client::class, inversedBy: 'groups')]
#[ORM\JoinColumn(nullable: false)]
private $client;
// ...
}
It is totallfy fine and correct that the Form it self submits and handles the Entity-Instance of the selected client. You almost never handle
$id
values. Thats one of the features of doctrine!
See the Symfony documentation for more information on how to use
EntityType
fields.
Note: From the naming you gave, I suspect you have the wrong relation, maybe it should be
OneToMany
? (Can you tell us howGroup
andClient
is related? Does 1 Group have multiple clients or vice versa?)
Sidenote: In rare cases, when you really need a Number related to an Entity (e.g. a textinput where user can enter a customer number which then translates to a real customer entity) you can use
DataTransformer
to translate such values. But this is not what you want here!