How to use a Symfony2.2 service from ouside of the controller? - php

I have a service in my Symfony app I know from the controller we can use it with the function $this->get('MyService');
but from a script outside of my controller how should I call it?

You have to register your outside-controller class as a service in your bundle's service configuration ( i'll assume yml configuration here )
services:
your_service_name:
class: Your/NonController/Class
arguments: ['#service_you_want_to_inject']
now in your class where you want to use the injected service:
// Your/NonController/Class.php
protected $myService;
// your 'service_you_want_to_inject' will be injected here automatically
public function __construct($my_service)
{
$this->myService = $my_service;
}
Remember for the Dependency Injection to happen you have to actually use this class as a service now - otherwise the injection will not happen automatically.
You can get your newly created service in a controller now as usual:
// 'service_you_want_to_inject' will be automatically injected in the constructor
$this->get('your_service_name');
There is also setter injection and property injection but that's out of this question's scope... Read more about DI in the Service Container chapter of the symfony documentation.

Related

how to use a service inside another service in symfony 2.6

I have a service setup in symfony 2.6 by name ge_lib and it looks like below
ge_lib:
class: GE\RestBundle\Services\GELib
arguments: [#session, #doctrine.orm.entity_manager, #manage_ge_proc]
inside GELib.php I have a requirement to use a function from another service manage_ge_proc
manage_ge_proc:
class: GE\RestBundle\Services\GEManageProcedure
arguments: [#doctrine.orm.entity_manager, #manage_ge_native_query]
if I try to use it this way, it is not working
$emailInv = $this->get('manage_ge_proc');
$sendStatus = $emailInv->pSendGeneralEmail(.....);
It gives error saying that unable to find any get function by that name. generally this -> $this->get('manage_ge_proc');works in any controller.But how do i use it in service?.
I tried $this->getContainer()->get('manage_ge_proc'); but it did not work.
This call is fetching service from DI container, which you dont have in your service
$this->get('manage_ge_proc');
It works in controller because DI container is automatically injected there.
Since you have this line in you services.yml, which tells Symfony to inject #manage_de_proc service into ge_lib constructor
arguments: [#session, #doctrine.orm.entity_manager, #manage_ge_proc]
you should be able to pick #manage_ge_proc from constructor like this:
public function __construct(
Session $session,
EntityManager $entityManager,
GEManageProcedure $manageGeProc
)
{
//... whatever you do in your constructor
$this->manageGeProc = $manageGeProc;
}

Symfony3 controller constructor injection is not working

I want to pass the EntityManager instance into the constructor of my controller, using this code:
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Doctrine\ORM\EntityManager;
class UserController extends Controller
{
public function __construct( EntityManager $entityManager )
{
// do some stuff with the entityManager
}
}
I do the constructor injection by putting the parameters into the service.yml file:
parameters:
# parameter_name: value
services:
# service_name:
# class: AppBundle\Directory\ClassName
# arguments: ["#another_service_name", "plain_value", "%parameter_name%"]
app.user_controller:
class: AppBundle\Controller\UserController
arguments: ['#doctrine.orm.entity_manager']
the service.yml is included in the config.yml and when I run
php bin/console debug:container app.user_controller
I get:
Information for Service "app.user_controller"
=============================================
------------------ -------------------------------------
Option Value
------------------ -------------------------------------
Service ID app.user_controller
Class AppBundle\Controller\UserController
Tags -
Public yes
Synthetic no
Lazy no
Shared yes
Abstract no
Autowired no
Autowiring Types -
------------------ -------------------------------------
However, calling a route which is mapped to my controller, I get:
FatalThrowableError in UserController.php line 17: Type error:
Argument 1 passed to
AppBundle\Controller\UserController::__construct() must be an instance
of Doctrine\ORM\EntityManager, none given, called in
/home/michel/Documents/Terminfinder/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php
on line 202
I cant figure out, why the EntityManager is not getting injected?
When using the base classController.php the Container is usually auto-wired by the framework in theControllerResolver.
Basically you are trying to mix up how things actually work.
To solve your problem you basically have two solutions:
Do no try to inject the dependency but fetch it directly from the Container from within your action/method.
public function listUsers(Request $request)
{
$em = $this->container->get('doctrine.orm.entity_manager');
}
Create a controller manually but not extend the Controller base class; and set ip up as a service
To go a bit further on this point, some people will advise to do not use the default Controller provided by Symfony.
While I totally understand their point of view, I'm slightly more moderated on the subject.
The idea behind injecting only the required dependencies is to avoid and force people to have thin controller, which is a good thing.
However, with a little of auto-determination, using the existing shortcut is much simpler.
A Controller / Action is nothing more but the glue between your Views and your Domain/Models.
Prevent yourself from doing too much in your Controller using the ContainerAware facility.
A Controller can thrown away without generate business changes in your system.
Since 2017 and Symfony 3.3+, there is native support for controllers as services.
You can keep your controller the way it is, since you're using constructor injection correctly.
Just modify your services.yml:
# app/config/services.yml
services:
_defaults:
autowire: true
AppBundle\:
resouces: ../../src/AppBundle
It will:
load all controllers and repositories as services
autowire contructor dependencies (in your case EntityManager)
Step further: repositories as services
Ther were many question on SO regarding Doctrine + repository + service + controller, so I've put down one general answer to a post. Definitelly check if you prefer constructor injection and services over static and service locators.
Did you use following pattern to call the controller AppBundle:Default:index? if yes that should be the problem. If you want to use controller as a service you have to use the pattern: app.controller_id:indexAction which uses the id of the service to load the controller.
Otherwise it will try to create an instance of the class without using the service container.
For more information see the symfony documentation about this topic https://symfony.com/doc/current/controller/service.html
The entity manager is available in a controller without needing to inject it. All it takes is:
$em = $this->getDoctrine()->getManager();

avoiding container strings in dependency injection in symfony

New to symfony and php. I was able to successfully define a service and inject the doctrine entity manager into it. It works fine but during the initialization I have to pass a string that contains the service name as follows:
$eRep = $this->container->get('employee_repository');
Can this be avoided? Can this be converted to something more elegant like
$eRep = $this->container->getEmployeeRepository();
The service is defined as:
services:
employee_repository:
class: AppBundle\Repository\EmployeeRepository
arguments: [#doctrine.orm.entity_manager]
Apologies for the noob question.
EDIT
Can I get access to a service container inside another class say EmployeeEnvelope and call as follows:
class EmployeeEnvelope{
public function getEmployeeRepository()
{
return $this->container->get('employee_repository');
}
}
If you're requesting the service from a controller, you can setup your controller to be a service too. Then you can pass the employee repository service to it using dependency injection.
That way you will not have the string reference in the controller, but in the configuration.
http://symfony.com/doc/current/cookbook/controller/service.html

Symfony2: get Doctrine in a generic PHP class

In a Symfony2 project, when you use a Controller, you can access Doctrine by calling getDoctrine() on this, i.e.:
$this->getDoctrine();
In this way, I can access the repository of such a Doctrine Entity.
Suppose to have a generic PHP class in a Symfony2 project. How can I retrieve Doctrine ?
I suppose that there is such a service to get it, but I don't know which one.
You can register this class as a service and inject whatever other services into it. Suppose you have GenericClass.php as follows:
class GenericClass
{
public function __construct()
{
// some cool stuff
}
}
You can register it as service (in your bundle's Resources/config/service.yml|xml usually) and inject Doctrine's entity manager into it:
services:
my_mailer:
class: Path/To/GenericClass
arguments: [doctrine.orm.entity_manager]
And it'll try to inject entity manager to (by default) constructor of GenericClass. So you just have to add argument for it:
public function __construct($entityManager)
{
// do something awesome with entity manager
}
If you are not sure what services are available in your application's DI container, you can find out by using command line tool: php app/console container:debug and it'll list all available services along with their aliases and classes.
After checking the symfony2 docs i figured out how to pass your service
in a custom method to break the default behavior.
Rewrite your configs like this:
services:
my_mailer:
class: Path/To/GenericClass
calls:
- [anotherMethodName, [doctrine.orm.entity_manager]]
So, the Service is now available in your other method.
public function anotherMethodName($entityManager)
{
// your magic
}
The Answer from Ondrej is absolutely correct, I just wanted to add this piece of the puzzle to this thread.

Access services inside a regular class

I have a regular class in my Symfony2 project:
class RangeColumn extends Column{
//...
}
Now inside this class is a render function, in which I'd like to use Twig or the Translation Service of Symfony2 to render a specific template. How do I access this services in a proper way?
Code example:
<?php
class MyRegularClass
{
private $translator;
public function __construct(Translator $translator)
{
$this->translator = $translator;
}
public function myFunction()
{
$this->translator->trans('sentence_to_translate');
}
}
And if you want your class to become a service:
In your services.yml file located in your bundle,
parameters:
my_regular_class.class: Vendor\MyBundle\Classes\MyRegularClass
services:
mybundle.classes.my_regular_class:
class: %my_regular_class.class%
arguments: [#translator]
For more details, see the chapter about the Symfony2 Service Container
Use dependency injection. It's a really simple concept.
You should simply pass (inject) needed services to your class.
If dependencies are obligatory pass them in a constructor. If they're optional use setters.
You might go further and delegate construction of your class to the dependency injection container (make a service out of it).
Services are no different from your "regular" class. It's just that their construction is delegated to the container.

Categories