How can i get the entityManager in some classes in Symfony ?
Tried to add a service but entityManager is null ...
What is the best way to do this in Symfony 4 ?
It's for call a function in a Repository from another class.
To access the entityManager inside your Service, you have to construct it first.
namespace App\Service;
use Doctrine\ORM\EntityManagerInterface;
class ServiceName
{
private $entityManager;
public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
public function myFunction()
{
$classRepo = $this->entityManager->getRepository(ClassName::class);
}
}
Related
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
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
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();
I followed the tutorial of Fabien Potiencier, about how to create your own Framework on top of the Symfony Components. Now i need a way. And I want to inject the Dependency Container to all my Controllers, without defining every single Controller as a Service.
In the orginal Symfony2 Framework all Controllers extends the Controller Class located in Symfony\Bundle\FrameworkBundle\Controller\Controller.php:
namespace Symfony\Bundle\FrameworkBundle\Controller;
class Controller extends ContainerAware
{
// ...
}
The Controller Class extends the ControllerAware Class, so you can do something like this in your Controller:
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
class MyController extends Controller
{
public function someAction()
{
$this->container->get('dependencie_xyz);
}
}
So my question is: How can I accomplish the same in my Framework?
It took me a while, but i finally figured out how the Symfony2 Framework does it.
In the SymfonyFrameworkBundle is a custom ControllerResolver, which call the setContainer Method on the resolved controller. The controller has to be a instance of the ContainerAwareInterface.
Simplified version:
class ContainerAwareControllerResolver extends ControllerResolver
{
private $container;
public __construct(ContainerInterface $container)
{
$this->container = $container;
parent::__construct();
}
public function getController(Request $request)
{
$controller = parent::getController($request);
if($controller instanceof ContainerAware ){
$controller->setContainer($this->container);
}
}
}
Source:
https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php
It is too simply. The next code will help you
namespace Symfony\Bundle\FrameworkBundle\Controller;
use Symfony\Component\DependencyInjection\ContainerInterface as Container;
use Symfony\Component\DependencyInjection\ContainerAware as ContainerAware;
class TestService extends ContainerAware
{
public function __construct(Container $container) {
// in your example from official doc 'dependencie_xyz' is a name of service
$this->setContainer($container); // call parent setContainer() method, for identifying container variable, from now you can access to ServiceContainer using $this->container variable
$test_param = $this->container->getParameter('test_param'); // get test_param from config.yml
}
}
in service.yml
write smthing like this
services:
test_service:
class: Symfony\Bundle\FrameworkBundle\TestService
arguments: ['#service_container']
and post service container as argument
If you are not implementing any interface on controller you can add the this way and it will work. This is a small modification to c4pone implementation.
/**
* Description of ContainerAwareControllerResolver
*
* #author sbc
*/
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Controller\ControllerResolver;
class ContainerAwareControllerResolver extends ControllerResolver {
private $container;
public function __construct(LoggerInterface $logger = null, ContainerInterface $container = null) {
parent::__construct($logger);
$this->container = $container;
}
protected function instantiateController($class) {
$new_class = new $class();
$new_class->setContainer($this->container);
return $new_class;
}
The Controller Class extends the ControllerAware Class, so you can do something like this in your Controller:
Well, this is not true. If we take a look at the signature of the ContainerAware class, we see that this added a setContainer method so we can set the container. Symfony2 has created the Controller::get method to make some live easier.
We can see how they do it in the source code:
/**
* Gets a service by id.
*
* #param string $id The service id
*
* #return object The service
*/
public function get($id)
{
return $this->container->get($id);
}
You can put this in your own Controller class and let all your controllers extend that controller class.
I needed to move my model from the controller method, so I got help to change it to a service. The service by itself works, but I need to be able to connect to doctrine and the kernel from inside of this service. At first I tried to enable doctrine, but that created problems. How can I make this work? I've followed docs and got this code. I have no idea why I got the error below. Thank you for your help in advance.
My config is:
CSVImport.php
namespace Tools\TFIBundle\Model;
use Doctrine\ORM\EntityManager;
class CSVImport {
protected $em;
public function __construct( EntityManager $em ) {
$this->em = $em;
}
app/config/config.yml
services:
csvimport:
class: Tools\TFIBundle\Model\CSVImport
arguments: [ #doctrine.orm.entity_manager ]
action in controller
$cvsimport = $this->get('csvimport');
MY ERROR
Catchable Fatal Error: Argument 1 passed to
Tools\TFIBundle\Model\CSVImport::__construct() must be an instance of
Doctrine\ORM\EntityManager, none given, called in
.../Tools/TFIBundle/Controller/DefaultController.php on line 58 and defined in
.../Tools/TFIBundle/Model/CSVImport.php line 12
EDIT, my working code:
service class code with Kernel attached to it
namespace Tools\TFIBundle\Model;
use Doctrine\ORM\EntityManager,
AppKernel;
class CSVImport {
protected $em;
protected $kernel;
protected $cacheDir;
public function __construct( EntityManager $em, AppKernel $k ) {
$this->em = $em;
$this->kernel = $k;
}
Try injecting #doctrine.orm.default_entity_manager.
On web I've found how to connect to Doctrine DBAL to be able to make queries on my own. But when i changed my configuration to this one:
app/config.yml
services:
csvimport:
class: Tools\TFIBundle\Model\CSVImport
arguments: [ #doctrine.dbal.connection, #doctrine.orm.entity_manager, #kernel ]
class definition
namespace Tools\TFIBundle\Model;
use Doctrine\ORM\EntityManager,
Doctrine\DBAL\Connection,
AppKernel;
class CSVImport {
protected $c;
protected $em;
protected $kernel;
public function __construct(Connection $c, EntityManager $em, AppKernel $k ) {
$this->c = $c;
$this->em = $em;
$this->kernel = $k;
}
i got error:
RuntimeException: The definition "csvimport" has a reference to an abstract definition "doctrine.dbal.connection". Abstract definitions cannot be the target of references.
Any ideas?