I have an Employer profile form and I am trying to link the State
where Employer
is located at with a City
this part is working alright but the FormType got so long and this feature will be required at other places of the website so I decided to move this logic inside an EventSubscriber and reuse it where ever I need it.
Problem I am having is I am trying to wrap my head around how to inject EntityManager
inside the EventSubscriber
class.
I know I can add the following code inside my services.yml
and that should do it buts its not working.
app.form.location:
class: AppBundle\Form\EventListener\AddStateFieldSubscriber
arguments: ['@doctrine.orm.entity_manager']
tags:
- { name: kernel.event_subscriber }
This is my EmployerProfileType
where I am calling my addEventSubscriber
which is AddStateFieldSubscriber()
class EmployerProfileType extends AbstractType
{
protected $em;
function __construct(EntityManager $em)
{
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstName', TextType::class)
->add('lastName', TextType::class)
->add('companyName', TextType::class)
->add('companyProfile', TextareaType::class)
->add('companyLogo', FileType::class, array(
'data_class' => null
));
$builder->addEventSubscriber(new AddStateFieldSubscriber());
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'AppBundle\Entity\EmployerProfile',
));
}
public function getName()
{
return 'app_bundle_emp_profile_type';
}
}
This is my AddStateFieldSubscriber
class where I need access to EntityManager
class AddStateFieldSubscriber implements EventSubscriberInterface
{
protected $em;
function __construct(EntityManager $em)
{
$this->em = $em;
}
public static function getSubscribedEvents()
{
// Tells the dispatcher that you want to listen on the form.pre_set_data
// event and that the preSetData method should be called.
return array(
FormEvents::PRE_SET_DATA => 'onPreSetData',
FormEvents::PRE_SUBMIT => 'onPreSubmit'
);
}
protected function addElements(FormInterface $form, States $province = null)
{
// Remove the submit button, we will place this at the end of the form later
// Add the province element
$form->add('state', EntityType::class, array(
'data' => $province,
'placeholder' => 'provide_state',
'class' => 'AdminBundle\Entity\States',
'mapped' => false)
);
// Cities are empty, unless we actually supplied a province
$cities = array();
if ($province) {
// Fetch the cities from specified province
$repo = $this->em->getRepository('AdminBundle:Cities');
$cities = $repo->findByStates($province, array('name' => 'asc'));
}
// Add the city element
$form->add('city', EntityType::class, array(
'placeholder' => 'provide_state_first',
'class' => 'AdminBundle\Entity\Cities',
'choices' => $cities,
));
}
function onPreSubmit(FormEvent $event) {
$form = $event->getForm();
$data = $event->getData();
// Note that the data is not yet hydrated into the entity.
$province = $this->em->getRepository('AdminBundle:States')->find($data['state']);
$this->addElements($form, $province);
}
function onPreSetData(FormEvent $event) {
$account = $event->getData();
$form = $event->getForm();
// We might have an empty account (when we insert a new account, for instance)
$province = $account->getCity() ? $account->getCity()->getStates() : null;
$this->addElements($form, $province);
}
}
The error I get is
Catchable Fatal Error: Argument 1 passed to AppBundle\Form\EventListener\AddStateFieldSubscriber::__construct() must be an instance of Doctrine\ORM\EntityManager, none given, called in /Users/shairyar/Sites/clickjobboard/src/AppBundle/Form/EmployerProfileType.php on line 48 and defined
I am injecting EntityManager
via service then why do I get this error?
If inside EmployerProfileType
I replace
$builder->addEventSubscriber(new AddStateFieldSubscriber();
to
$builder->addEventSubscriber(new AddStateFieldSubscriber($this->em));
then things start working fine.
I thought in Symfony we are supposed to inject the dependencies by creating services? So how can I inject EntityManager
inside my AddStateFieldSubscriber()
class
What am i doing wrong? may be I am over thinking about it.
Will appreciate any feedback.