yevg
yevg

Reputation: 1966

Symfony PHP - Using service within another service

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: enter image description here

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

Answers (1)

fubar
fubar

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

Related Questions