Service DependencyInjection in Symfony2 - symfony

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?

Related

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

Symfony Dependency injection with EntityMenager

I had to call controller in service. In that manner I had created connstruct function and add parameter EntityMenager
class UsersController extends Controller
{
private $em;
public function __construct(EntityManager $em) {
$this->em = $em;
}
and defined service for that controller
services:
user_controller:
class: AppBundle\Controller\UsersController
arguments:
['#doctrine.orm.entity_manager']
when I call that service
$usersContainer = $this->get('user_controller');
in other controllers everything is fine.
But when I call self controller I get error
Catchable Fatal Error:
Argument 1 passed to AppBundle\Controller\UsersController::__construct()
must be an instance of Doctrine\ORM\EntityManager, none given,
Where I making mistake?
I just do ugly hack and solve problem at this moment.
I had removed __construc class and add EntityManager as needed parameter to function that needs EntityManager class.
public function getLoggedUserData($loggedUserId, $entityManager)
{
$user = $entityManager->getRepository('...')
$newRequests = $entityManager->getRepository('...')
You can only define a Controller as service, if it is a simple class (not extending Controller).
See : http://symfony.com/doc/current/cookbook/controller/service.html
And particularly :
http://symfony.com/doc/current/cookbook/controller/service.html#alternatives-to-base-controller-methods

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();

Symfony2 getdoctrine outside of Model/Controller

I'm trying to getDoctrine() outside of the controller.
I've created this service:
config/services.yml
services:
update_command:
class: project\projBundle\Command\Update
arguments: ['#doctrine.orm.entity_manager']
and in my app/config/config.yml
imports:
- { resource: "#projectprojBundle/Resources/config/services.yml" }
so and the class that I want to use:
namespace project\projBundle\Command;
use Doctrine\ORM\EntityManager;
class Update {
protected $em;
public function __construct(EntityManager $em) {
$this->em = $em;
}
but every time I want to do this: (I'm doing this right?)
$up = new Update();
i got this error:
Catchable Fatal Error: Argument 1 passed to ...\Update::__construct() must be an instance of Doctrine\ORM\EntityManager, none given, called in .../Update.php line 7
Simple solution
If you're implementing a Symfony command (that can be executed in a cron tab), you can access the service container from the command.
<?php
namespace MyProject\MyBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class UpdateCommand extends ContainerAwareCommand
{
protected $em;
protected function configure()
{
$this->setName('myproject:mybundle:update') ;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->em = $this->getContainer()->get('doctrine.orm.entity_manager');
}
}
That way, you get the entity manager from a command and don't need to declare this class as a service. You can therefore remove the configuration you added in the services.yml file.
An other solution (cleaner)
This solution allows better separation of concerns and can therefore be easily unit tested and reused in other parts of your Symfony application (not only as a command).
Move all the logic part of your "update" command to a dedicated class that you will declare as a service:
<?php
namespace MyProject\MyBundle\Service;
use Doctrine\ORM\EntityManager;
class MyUpdater
{
protected $em;
public function __construct($em)
{
$this->em = $em;
}
public function runUpdate()
{
// All your logic code here
}
}
Declare it as a service in your services.yml file:
services:
myproject.mybundle.myupdater:
class: MyProject\MyBundle\Service\MyUpdater
arguments: ['#doctrine.orm.entity_manager']
Simply call your service from your command :
<?php
namespace MyProject\MyBundle\Command;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class UpdateCommand extends ContainerAwareCommand
{
protected function configure()
{
$this->setName('myproject:mybundle:update') ;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$myUpdater = $this->getContainer()->get('myproject.mybundle.myupdater');
$myUpdater->runUpdate();
}
}
You have to either inject your newly created #update_command service or get it from the container in order to have the #doctrine.orm.entity_manager service injected automatically.
You're just creating the object with no argument, not a service. Update expects to retrieve an entity manager instance but you don't provide it.
$up = new Update();
In a ContainerAware class like a controller get your service like this:
$up = $this->container->get('update_command');
Otherwise turn the class where you want to use the update_command into a service aswell and inject #update_command as you did with the entity manager in the service itself.
remove below codes in app/config/config.yml, your services.yml will be autoload...
imports:
- { resource: "#projectprojBundle/Resources/config/services.yml" }
in a Action new a instance you can do:
$up = $this->get('update_command');

Unable to inject EntityManager into Twig extension

I have a problem injecting the EntityManger into a Symfony2 twig-extension. I did the following:
I registered a new twig extension and created a class. All of it is working.
Now I wanted to get access to the database and tried to inject the doctrine EntityManager. My first step was to add the EM as parameter to the constructor:
use XYZ\BlubBundle\Utils\SessionHelper;
class SessionHelperExtension extends \Twig_Extension
{
private $em;
private $conn;
protected $sessionHelper;
public function __construct(\Doctrine\ORM\EntityManager $em, \XYZ\BlubBundle\Utils\SessionHelper $sessionHelper) {
$this->em = $em;
$this->conn = $em->getConnection();
$this->sessionHelper = $sessionHelper;
}
[...]
}
?>
Then I added the following lines to the service.yaml:
twig.extension.sessionHelper:
class: XYZ\BlubBundle\Extensions\SessionHelperExtension
arguments: [#session_helper, #doctrine.orm.entity_manager]
tags:
- { name: twig.extension }
My own Service "sessionHelper" gets injected without a problem, but the EntityManager is always "null". What am I doing wrong here?
EDIT:
I get the following exception:
Catchable Fatal Error: Argument 2 passed to
XYZ\BlubBundle\Extensions\SessionHelperExtension::__construct() must be an instance of
Doctrine\ORM\EntityManager, none given,
called in /.../Symfony/app/cache/dev/appDevDebugProjectContainer.php on line 2918 and
defined in /.../Symfony/src/XYZ/BlubBundle/Extensions/SessionHelperExtension.php line 12
public function __construct(
\Doctrine\ORM\EntityManager $em,
\XYZ\BlubBundle\Utils\SessionHelper $sessionHelper
) {
is wrong — you need to keep the same order like in the yml:
public function __construct(
\XYZ\BlubBundle\Utils\SessionHelper $sessionHelper,
\Doctrine\ORM\EntityManager $em
) {
Update
Try this: http://www.coderelic.com/2012/06/querying-the-database-from-a-twig-extension-in-symfony-2/

Resources