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.
Related
For my company I'm working on a Symfony webapp that needs to fetch users and businesses from the database.
However I am forced to use an ODBC connection. I went with pdo_odbc and this is working fine from the controller (Connection, queries, fetching, rendering).
But I'm a bit lost on how to use Entities and Repositories if I'm unable to use Doctrine to connect.
So what I'm doing now is connecting to the database, do queries, fetching data and rendering to the views in one controller function. Without using Entities or Repositories, this is obviously not what it should be.
If any of you need more information feel free to comment.
PS: I'm new to Symfony in general, so examples are much appreciated
We're doing the same stuff on some projects.
We've done the following steps:
Write Repositories, but instead of using the Doctrine ORM and QueryBuilder, we just use the PDO connection with PDO statements.
We create Models instead of Entites. Every Model has a "setFromDb()" function which receives an array of data. Those informations will be matched to the attributes of the Model.
Within services, Controller whatsoever we're only working with the models.
The repositories we've written just are classes that are defined as services and will receive the doctrine connection as constructor injection. Then you can get the connection and work with PDO.
Example for a repository class (note that we just call them repositories because they handle the database queries, but they have nothing to do with the Repository classes from Symfony / Doctrine)
class DemoRepositoryClass
{
private $connection;
public function __construct(Registry $doctrine)
{
// Get the database connection from doctrine
$this->connection = $doctrine->getConnection();
}
public function test()
{
$query = "SELECT * FROM XXX WHERE FOO = 'BAZ";
$stmt = $this->conncetion->prepare($query);
// [...] Do as always with PDO;
}
}
This class will be defined as service in the services.yml
app.demo_repository_class:
class: AppBundle\Path\DemoRepositoryClass
arguments: ['#doctrine']
public: true
With that, you can call the service functions from the controller as example:
// In a controller action/function
$this->get('app.demo_repository_class')->test();
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;
}
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"]
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
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.