avoiding container strings in dependency injection in symfony - php

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

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

Creating a symfony service that can access doctrine

I have a signupAction inside a controller. I would like this signupAction to call another service which then will create an account. So I created a service called AccountService which extends Controller as I would like to get access to doctrine ($this->getDoctrine()...) in order to save an account to the database. However when i cann my service, it tells me it has no access to the container (null).
if (!$this->container->has('doctrine')) {
The above line fails as container is null.
This is how I call the service:
$accountService = $this->get('app.account');
$accountService->createAccount($account);
And i configured it in services.yml as:
services:
app.account:
class: AppBundle\Service\AccountService
Can anyone help me figure out how to get this working? Or as a better ideas how to have services called to deal with database instead of it all in my actions in controllers?
I have symfony 3.2
I believe that most people starting from scratch would use ORM, I didn't because I had existing PHP code working with PDO SQL. Here is an example showing how to access Doctrine DB connection:
In [YourBundle]\Resources\config\services.yml
services:
#dependency injection services
pdo_connection:
class: [YourBundle]\DependencyInjection\PDOManagement\PdoConnection
arguments: ["#doctrine.dbal.default_connection"]
Then in [YourBundle]\DependencyInjection\PDOManagement\PdoConnection.php
<?php
namespace [YourBundle]\DependencyInjection\PDOManagement;
use Doctrine\DBAL;
class PdoConnection {
protected $db;
public function __construct($dbalConnection){
$this->db = $dbalConnection;
}
}
?>
this->db of class PdoConnection will have access to the DB connection after constructor.
I let you figure out how to use it according to your need.

Inject kernel.root_dir to entity constructor in Symfony2

i searh and read a lot of same question but ever i got the same error :/
I create a service:
parameters:
tbackend.report.class: T\BackendBundle\Entity\Report
services:
tbackend.entity.report:
class: %tbackend.report.class%
arguments: ["%kernel.root_dir%"]
And i has this in T\BackendBundle\Entity\Report:
public function __construct($rootDir){
$this->rootDir = $rootDir;
}
When i try to create new Report(); i receive this msg:
Warning: Missing argument 1 for T\BackendBundle\Entity\Report::__construct(), called in /var/www/test/t_study/src/T/BackendBundle/Entity/ReportRepository.php on line 62 and defined
Considerations: i know the services.yml is called, i has more services in this file and all work ok (Loginhandlers, etc), i only add one more (tbackend.entity.report)
What is wrong with that? :( I dont know if need more for know about the problem. I follow symfony2 service container guide
http://symfony.com/doc/master/book/service_container.html
Basically I try not to use DIR in the Entity when moving files
Ty
When instantiating a class, you use normal PHP. Symfony isn't some magic that hooks into the instantiating process of PHP to automatically inject things in the constructor.
If you want to get a service, you either have to inject the service in the class you need it or you have the containe rin the class (for instance, in the controller) and retrieve the service from the container.
$report = $this->container->get('tbackend.entity.report');
or: (which is a much better practice in all cases except from controllers)
class WhereINeedTheReport
{
private $report;
public function __construct(Report $report)
{
$this->report = $report;
}
}
services:
# ...
where_i_need_the_report:
class: ...
arguments: ["#tbackend.entity.report"]

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

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.

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.

Categories