Reputation: 1966
I have a Symfony 4 app that calls a database service from within a session service.
The database service has a __construct
methods that grabs db credentials from services.yaml
DB Service
namespace App\Services;
class Database {
private $conn;
public function __construct($host, $name, $user, $pass){
$this->conn = mysqli_connect($host,$user,$pass,$name) or die('error: cannot connect');
}
//...
}
config/services.yaml
services:
App\Services\Database:
arguments:
$host: '1.2.3.4.5'
$name: 'database_name'
$user: 'username'
$pass: 'password'
I am using this service in a Sessions service used by a Login controller.
Login Controller
namespace App\Controller;
use App\Services\Database;
use App\Services\Session;
// ...
// ...
if($login_valid){
//...
$session = new Session();
$session->create();
}
Session Service
namespace App\Services;
use App\Services\Database;
class Session {
private $DB;
public function __construct(){
$this->DB = new Database(); // ** ERROR **
}
public function create(){
$this->DB->insert('a new session'); // (pseudo-code)
}
//...
}
This throws an error when setting the DB service instance in the Session service. The error is as follows:
The __construct
method for DB is called which takes the 4 arguments (defined globally in services.yaml
) which I am not providing when instantiating the DB service inside the Session service.
But this is never the case when I instantiate the DB service this way directly in a controller.
Moreover, isnt one of the benefits of using __construct
with service arguments set in services.yaml
to avoid having to pass these arguments every time?
Symfony knows to fire __construct
when the DB service is called, and the arguments it needs are set right there in services.yaml
- what gives?
Upvotes: 0
Views: 1807
Reputation: 17378
In short you need to use dependency injection.
You are correct that by registering the Database
class arguments in services.yml
, Symfony is able to inject these values during instantion. However, this is only done automatically when using the dependency injection container.
You will need to use this in both your LoginController
and in your Session
service.
LoginController
namespace App\Controller
use App\Services\Session;
class LoginController
{
private $session;
public function __construct(Session $session)
{
$this->session = $session;
}
}
Session
namespace App\Services;
use App\Services\Database;
class Session
{
private $db;
public function __construct(Database $db)
{
$this->db = $db;
}
public function create(){
$this->db->insert('a new session'); // (pseudo-code)
}
}
Upvotes: 3