I have recently created an admin application to manage all our users, customers etc...
The application is configured with 2 entitymanagers to get and set data to a 'staging' database and a 'production' database.
All fine, fetching data from the different databases is no problem but when a form is submitted, it always takes the default entity manager to validate and save the information entered.
Can I specify somewhere which entity manager should be used by a form on creation or at $form->handleRequest($request);
?
Config:
doctrine:
dbal:
default_connection: default
connections:
default:
driver: pdo_mysql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_name2%'
user: '%database_user2%'
password: '%database_password2%'
charset: UTF8
prod:
driver: pdo_mysql
host: '%database_host%'
port: '%database_port%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
charset: UTF8
orm:
auto_generate_proxy_classes: '%kernel.debug%'
default_entity_manager: staging
entity_managers:
staging:
naming_strategy: doctrine.orm.naming_strategy.underscore
connection: default
mappings:
AppBundle: ~
prod:
naming_strategy: doctrine.orm.naming_strategy.underscore
connection: prod
mappings:
AppBundle: ~
CustomerController@CreateAction:
public function createAction(Request $request, $id, RegistryInterface $registry, $_env)
{
$em = $registry->getManager($_env);
$customer = $em->getRepository('AppBundle:Customer')->find($id);
$customer->init($this->getUser());
$form = $this->createForm(CustomerForm::class, $customer, ['action' => $this->generateUrl('customers_edit', ['id' => $id, '_env' => $_env]), 'trait_choices' => [$em]]);
$form->handleRequest($request);
I can't find a word on this subject in the docs of Symfony...
EDIT
CustomerType code:
<?php
namespace AppBundle\Form;
use AppBundle\Entity\Role;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CustomerType extends AbstractType
{
public function init($em)
{
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
if (isset($options['trait_choices'])) {
call_user_func_array(array($this, 'init'), $options['trait_choices']);
}
$builder->add('companyName', TextType::class, [
'label' => 'label.name',
'required' => true
]);
$builder->add('street', TextType::class, [
'label' => 'label.street',
'required' => true
]);
$builder->add('streetNr', NumberType::class, [
'label' => 'label.street_nr',
'required' => true
]);
$builder->add('streetBox', TextType::class, [
'label' => 'label.street_box',
'required' => false
]);
$builder->add('postalCode', TextType::class, [
'label' => 'label.postal_code',
'required' => true
]);
$builder->add('city', TextType::class, [
'label' => 'label.city',
'required' => true
]);
$builder->add('country', EntityType::class, [
'class' => 'AppBundle\Entity\Country',
'choice_label' => 'name',
'label' => 'label.country',
'required' => true,
'choice_translation_domain' => 'messages',
'em' => $this->em
]);
$builder->add('vatNr', TextType::class, [
'label' => 'label.vat',
'required' => false
]);
$builder->add('phone', TextType::class, [
'label' => 'label.phone',
'required' => false
]);
$builder->add('email', TextType::class, [
'label' => 'label.email',
'required' => true
]);
$builder->add('roles', EntityType::class, [
'class' => Role::class,
'query_builder' => function (EntityRepository $er) {
return $er->createQueryBuilder('r')
->where('r.type = ?1')
->setParameter(1, Role::TYPE_CUSTOMER);
},
'label' => 'Roles',
'multiple' => true,
'expanded' => true,
'choice_label' => 'displayName',
'attr' => [
'class' => 'roles'
],
'choice_translation_domain' => 'messages',
'em' => $this->em
]);
$builder->add('leadSources', EntityType::class, [
'label' => 'label.origin_lead',
'class' => 'AppBundle\Entity\LM\LeadSource',
'multiple' => true,
'expanded' => true,
'choice_label' => 'name',
'choice_translation_domain' => 'messages',
'em' => $this->em
]);
$builder->addEventListener(FormEvents::PRE_SUBMIT, array($this, 'onPreSubmitListener'));
}
public function onPreSubmitListener(FormEvent $event)
{
$customer = $event->getForm()->getData();
if ($customer->getIdentifier() == null) {
$customer->setIdentifier(uniqid('dummy'));
$event->getForm()->setData($customer);
} else {
$event->getForm()->setData($customer);
}
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => 'AppBundle\Entity\Customer',
'trait_choices' => null,
'allow_extra_fields' => true,
]);
}
}
How is the value for $_env injected? Try to dump it to see that it actually returns what you expect it to return ("prod" or "staging")
The behavior you experience implies that it is probably always null, so the default entity manager is created in all cases.
Try something like $env = $container->getParameter("kernel.environment")
PS Your use of environments is a bit weird. It is probably not such a good idea to risk accessing your prod db from your dev or staging environments. Try to use the parameters and .env files as they should be used.
UPDATE:
You can pass an entity manager to your form type, using the options array when you call the createForm function
Something like
$form = $this->createForm(
YourFormType::class,
$yourEntity,
[
'entityManager' => $this->getDoctrine()->getManager($_env),
]
);
And then in your buildForm function you can retrieve it from the options array.
UPDATE 2
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'entityManager' => null,
]);
}