Symfony3 Use Entity Manager in Custom Container - symfony

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

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';
}
}

Can disabling autowiring and using annotation instead for services in Symfony 3?

In the DI there is Autowiring, annotation definition and PHP definition.
In Symfony 3.3 the autowiring is enabled by default. So if I disable the autowiring, can I use the annotation to define a service?
class Foo
{
/**
* #Inject({"my.specific.service"})
*/
public function __construct(Bar $param1)
{
}
}
Update : Use JMSDiExtraBundle
namespace MediaBundle\Net;
use JMS\DiExtraBundle\Annotation\Inject;
use JMS\DiExtraBundle\Annotation\InjectParams;
use JMS\DiExtraBundle\Annotation\Service;
/**
* #Service("some.service.id", public=false, environments = {"prod", "test", "dev"})
*/
class Foo
{
private $em;
private $session;
/**
* #InjectParams({
* "em" = #Inject("doctrine.orm.entity_manager"),
* "session" = #Inject("session")
* })
*/
public function __construct($em, $session)
{
$this->em = $em;
$this->session = $session;
}
}
Calling the service in the controller:
namespace MediaBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
class DefaultController extends Controller
{
/**
* #Route("/media")
*/
public function indexAction()
{
$someService = $this->get('some.service.id');
return $this->render('MediaBundle:Default:index.html.twig');
}
}
Result : You have requested a non-existent service "some.service.id".
Is your service injected somewhere? If not, it will be dropped from the container due to public=false, see http://symfony.com/blog/new-in-symfony-3-2-improved-private-services

Fosuserbundle override event listener

I'm trying to override the LastLoginListener to add functionality to it.
I;m trying to do it as described here
It seems
In AppBundle\DependencyInjection\OverrideServiceCompilerPass.php
<?php
namespace AppBundle\DependencyInjection\Compiler;
use AppBundle\EventListener\LastLoginListener;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
class OverrideServiceCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$definition = $container->getDefinition('"fos_user.security.interactive_login_listener');
$definition->setClass(LastLoginListener::class);
}
services.yml
services:
app.login_listener:
class: AppBundle\EventListener\LastLoginListener
arguments: []
tags:
- { name: kernel.event_subscriber }
The listener itself is copied from the bundle.
The autoloader expected class "AppBundle\DependencyInjection\OverrideServiceCompilerPass" to be defined in file "/vendor/composer/../../src/AppBundle/DependencyInjection/OverrideServiceCompilerPass.php". The file was found but the class was not in it, the class name or namespace probably has a typo.
in DebugClassLoader.php (line 261)
My goal is to add the ip address of the last login with the listener, but I'll need to create another to add a role and a registration date
I'm trying to do it "the right way" instead of doing something hackish
Its much better to use success_handler and failure_handler services.
# app/config/security.yml
firewalls:
main:
...
form_login:
...
success_handler: authentication_success_handler
failure_handler: authentication_failure_handler
Next you need to register your services and add arguments that fit your needs (probably #router and #doctrine.orm.entity_manager)
# app/config/services.yml
authentication_success_handler:
class: AppBundle\Handler\AuthenticationSuccessHandler
arguments: ['#router', '#doctrine.orm.entity_manager']
authentication_failure_handler:
class: AppBundle\Handler\AuthenticationFailureHandler
arguments: ['#router', '#doctrine.orm.entity_manager']
Then you need to create your services
// src/AppBundle/Handler/AuthenticationSuccessHandler.php
<?php
namespace AppBundle\Handler;
use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Router;
use Doctrine\Common\Persistence\ObjectManager;
class AuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface {
protected $router;
private $em;
public function __construct(Router $router, ObjectManager $em) {
$this->router = $router;
$this->em = $om;
}
public function onAuthenticationSuccess(Request $request, AuthenticationException $exception) {
// your code here - creating new object. redirects etc.
}
}
and
// src/AppBundle/Handler/AuthenticationFailureHandler.php
<?php
namespace AppBundle\Handler;
use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Router;
use Doctrine\Common\Persistence\ObjectManager;
class AuthenticationFailureHandler implements AuthenticationFailureHandlerInterface {
protected $router;
private $em;
public function __construct(Router $router, ObjectManager $em) {
$this->router = $router;
$this->em = $om;
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception) {
// your code here - creating new object. redirects etc.
}
}
If you want to hook into another FOSUserBundle Controller use this

How can I use doctrine from a static method

I always use doctrine from controllers or from entity repository classes, now I am trying to use it from a static class but I can't find any example on how to do id.
Basically I'd need (I think) a way to create the entity manager in a static method.
thanks
M
You may call a setter function, injecting entity manager, where you call the static method:
MyController
Class MyController extends Controller
{
public function newAction()
{
$entityManager = $this->getDoctrine()->getManager();
SomeClass::setEntityManager($entityManager);
$result = SomeClass::myStaticMethod();
}
}
SomeClass
Class SomeClass
{
private static $entityManager;
public static function setEntityManager($entityManager)
{
self::$entityManager = $entityManager;
}
public static function myStaticMethod()
{
return $entityManager->getRepository(SomeEntity::class)->findAll();
}
}
I'm not sure from your question what you mean by static class/method, some code example might help. But you could declare this class as a service, which it sounds like it might be meant to be anyway, and then inject the entity manager as a dependency.
services.yml
services:
my_service:
class: Acme\AppBundle\Services\MyService
arguments: ["#doctrine.orm.entity_manager"]
Then in your class you will have the entity manager available like this:
<?php
namespace Acme\AppBundle\Services;
use Doctrine\ORM\EntityManager;
class MyService
{
/**
* Entity Manager
*
* #var Doctrine\ORM\EntityManager
*/
protected $em;
public function __construct(EntityManager $em)
{
$this->em = $em;
}
...
}
And you can then use this service in your controllers like so:
$this->get('my_service')->doSomething();

Inject service in FOSRest Controller

I am new at symfony and trying to create REST api using FOSRest Bundle. Also i want to use flysystem library as service in my controllers. It is simple as that
class FileController extends FOSRestController
{
public function getFilesAction()
{
$filesystem = $this->container->get('oneup_flysystem.application_filesystem');
...
}
}
This works fine, but my idea is to Inject this service into FileController so i can use $filesystem service in every method in my controller.
I read about it, that I have to make my controller as service, but then something went wrong. What is the proper way to make this injection.
We use something like this:
YourBundle/Resources/config/services.yml
controller.file:
class: YourBundle\Controller\FileController
arguments:
- #yourFileService
- #service_container
YourBundle/Controller/FileController.php
/**
* #Route("/file", service="controller.file")
*/
class FileController extends Controller
{
/**
* #var Filesystem
*/
private $filesystem;
/**
* #param Filesystem $filesystem
* #param $container
*/
public function __construct(
Filesystem $filesystem,
$container
) {
$this->filesystem = $filesystem;
$this->container = $container;
}

Resources