Inject EntityManager in an EventSubscriberInterface - symfony

I've done an EventSubscriber, but I need to use EntityManager in. I've filled the services.yml like this:
app.subscriber.tube_dynamic_field:
class: AppBundle\Form\EventListener\TubeDynamicFieldSubscriber
arguments: ["#doctrine.orm.entity_manager"]
I try to use it in the EventSubscriber like this:
class TubeDynamicFieldSubscriber implements EventSubscriberInterface
{
private $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
...
}
Finally I use the EventSubscriber in a FormType like this:
class TubeType extends AbstractType
{
private $dynamicFieldSubscriber;
public function __construct(TubeDynamicFieldSubscriber $subscriber)
{
$this->dynamicFieldSubscriber = $suscriber;
}
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->addEventSubscriber($this->dynamicFieldSubscriber);
}
...
}
But I've an error:
Type error: Argument 1 passed to AppBundle\Form\TubeType::__construct()
must be an instance of AppBundle\Form\EventListener
\TubeDynamicFieldSubscriber, none given
I've try to use it: $builder->addEventSubscriber(new TubeDynamicFieldSuscriber()) but I've again an error: it don't recover the EntityManager.
If you know how I can inject the EntityManager in the EventSubscriber :)
Thanks a lot.

While your code snippets are not very clear, if your form type has dependencies, it needs to be registered in the service container so that Symfony (and the form factory) know how to construct it.
services:
my_form_type:
class: AppBundle\Form\TubeType
arguments: ["#my_event_subscriber"]
tags: [{ name: form.type }]
However, a better way of doing this is probably to inject the entity manager in the form type:
services:
my_form_type:
class: AppBundle\Form\TubeType
arguments: ["#doctrine.orm.entity_manager"]
tags: [{ name: form.type }]
That way, in your code, you can just do:
$builder->addEventSubscriber(new TubeDynamicFieldSuscriber($this->manager));

Related

Could not load type "app_filter": class does not exist

I have upgraded the symfony 2.8 project to symfony 3.4. After fixing some issue I am getting the above issue when loading the page which has form with filters.
The app_filter attribute is configured in my form.yml file inside the bundle/resources/config directory and it looks like the below,
parameters:
app.abstract_filter.form.type.class: AppBundle\Form\Type\Filter\FilterType
services:
app.abstract_filter.form.type:
class: '%app.abstract_filter.form.type.class%'
arguments:
- '#translator.default'
- '#doctrine.orm.entity_manager'
tags:
- { name: form.type, alias: app_filter}
app.abstract_filter.form:
class: Symfony\Component\Form\Form
factory: ['#form.factory', createNamed]
arguments:
- 'app_filter'
- '%app.abstract_filter.form.type.class%'
app_abstract_fitler_form_type class:
namespace AppBundle\Form\Type\Filter;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Translation\Translator;
class FilterType extends AbstractType
{
/** #var Translator */
protected $translator;
/** #var EntityManager */
protected $entityManager;
public function __construct(Translator $translator, EntityManager $entityManager)
{
$this->translator = $translator;
$this->entityManager = $entityManager;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
}
public function getName()
{
return 'app_filter';
}
}

Symfony3 Use Entity Manager in Custom Container

I want to create HelperController for my project. I generate a controller with doctrine:generate:controller and I need to use entity manager in it.
I enjected to services.yml but it is giving an error like this:
Argument 1 passed to CampingBundle\Controller\HelperController::__construct() must be an instance of Doctrine\ORM\EntityManager, none given ...
My Controller Code :
namespace CampingBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Doctrine\ORM\EntityManager;
class HelperController extends Controller
{
protected $manager;
public function __construct(EntityManager $manager)
{
$this->manager = $manager;
}
My Services.yml :
services:
camping.helper_controller:
class: CampingBundle\Controller\HelperController
arguments: ["#doctrine.orm.entity_manager"]
Why it doesn't work ? Shoudl I clear cache or something else or is there anything wrong in definition ?
Thanks
Try to use EntityManagerInterface and remove extends Controller.
Check this link if you need CAS (Controllers as Services).
Change protected $manager; to private $manager;
namespace CampingBundle\Controller;
use Doctrine\ORM\EntityManagerInterface;
class HelperController
{
/**
* #var EntityManagerInterface $entityManager
*/
private $entityManager;
/**
* #param $entityManager
*/
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
}
I'll leave my two cents here as I had same issue and fixed it by adding tags to service.
something.validate.some_service:
class: Path\To\Some\Validator
arguments:
- '#doctrine.orm.entity_manager'
tags:
- { name: validator.constraint_validator, alias: some_validator_alias }
How to Work with Service Tags by Symfony

Symonfy: How to use doctrine manager in form subscriber?

I have a form subscriber, i want to use doctrine manager in it. but i got the error message:
"Catchable Fatal Error: Argument 1 passed to ...\ProductEavAttributesSubscriber::__construct() must be an instance of Doctrine\ORM\EntityManager, instance of Symfony\Component\Form\FormFactory given。
there is my subscriber file code:
namespace Demo\Bundle\ProductBundle\EventListener;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\EntityManager;
class ProductEavAttributesSubscriber implements EventSubscriberInterface
{
private $entityManager;
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
// coding
}
in service.yml
demo.product.eav.attribute:
class: ...\EventListener\ProductEntityAttributesSubscriber
arguments: ["#doctrine.orm.entity_manager"]
tags:
- { name: form.type, alias: product_eav_attribute }
In form type:
$builder->add('specifications', ProductEavAttributeType::class);
In the ProductEavAttributeType file:
class ProductEavAttributeType extends AbstractType
{
/**
* #param FormBuilderInterface $builder
* #param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$factory = $builder->getFormFactory();
$productEavAttributes = new ProductEavAttributesSubscriber($factory);
$builder->addEventSubscriber($productEavAttributes);
}
}
So, how to do now?

Symfony2 Form Type as a service with dynamic parameter

I'm really interested to know if there is a way to call a service with a dynamic parameter (a string for example)?
Actually I need this for a form type (define as a service), which makes it a little more complex.
The form type :
class MyFormType extends AbstractType
{
private $em;
private $parameter;
public function __construct(EntityManager $em, $parameter)
{
$this->em = $em;
$this->parameter = $parameter;
}
// ...
}
The service config
my.form_type:
class: My\Form\Type\Class
arguments: [ #doctrine.orm.entity_manager ]
tags:
- { name: form.type, alias: form_name }
Then when I need to use it in another form type:
class SecondFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('custom', 'my.form_type');
;
}
}
I would like to know how to set the "parameters" attribute in the first form type class.
If I was in a controller, I would be able to create some getter/setter methods but here I'm stuck in the form type.
I actually don't instantiate the form type myself, because I also need to inject it the entity manager, that's why I defined it as a service.

HWIOAuthBundle custom service provider arguments

I'm trying to set up HWIOAuthBundle to work with FOSUserBundle.
While making my own User Provider that extends FOSUBUserProvider, I did the following:
namespace Naroga\Reader\CommonBundle\Service\Security;
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider;
use HWI\Bundle\OAuthBundle\OAuth\Response\UserResponseInterface;
class NarogaUserProvider extends FOSUBUserProvider {
public function loadUserByOAuthUserResponse(UserResponseInterface $response) {
[...]
}
}
My services.yml is as follows:
naroga.reader.common.security.user_provider:
class: Naroga\Reader\CommonBundle\Service\Security\NarogaUserProvider
arguments: [ #fos_user.user_manager ]
Whenever I run the program, I get the following error:
Argument 2 passed to HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider::__construct() must be of the type array, none given, called in
This makes great sense, because FOSUBUserProvider::__construct's signature is public function __construct(UserManagerInterface $userManager, array $properties).
I have no idea what to define as being my second parameter to my service so it can override FOSUBUserProvider. I've been googling it and all I find is people with the same question, no answers.
I'd be forever grateful to the gentle soul that tells me what the second parameter must be in order to comply with FOSUBUserProvider's signature.
Thank you.
The second argument is used for mapping.
As I understand, this is the name corresponding OAuth service and name of field in your entity.
For example, you can send them as follows:
naroga.reader.common.security.user_provider:
class: Naroga\Reader\CommonBundle\Service\Security\NarogaUserProvider
arguments: [ #fos_user.user_manager, { facebook: facebookId, twitter: twitterId } ]
In case you would like to pass also some additional arguments, let's say fire an event using dispatcher which was my case, just overwrite the constructor.
use HWI\Bundle\OAuthBundle\Security\Core\User\FOSUBUserProvider as BaseClass;
FOSUBUserProvider extends BaseClass
{
/**
* #var EventDispatcherInterface
*/
private $eventDispatcher;
/**
* Constructor.
*
* #param UserManagerInterface $userManager FOSUB user provider.
* #param array $properties Property mapping.
* #param EventDispatcherInterface $eventDispatcher
*/
public function __construct(
UserManagerInterface $userManager,
array $properties,
EventDispatcherInterface $eventDispatcher)
{
$this->userManager = $userManager;
$this->properties = array_merge($this->properties, $properties);
$this->accessor = PropertyAccess::createPropertyAccessor();
$this->eventDispatcher = $eventDispatcher;
}
And the service definition:
tb_user_provider:
class: "%tb_user_provider.class%"
arguments: [#fos_user.user_manager, { facebook: facebook_id }, #event_dispatcher]

Resources