Symfony PHP - 在另一个服务中使用服务

Symfony PHP - Using service within another service

我有一个从会话服务中调用数据库服务的 Symfony 4 应用程序。

数据库服务有一个 __construct 方法可以从 services.yaml

获取数据库凭据

数据库服务

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'

我在登录控制器使用的会话服务中使用此服务。

登录控制器

namespace App\Controller;

use App\Services\Database;
use App\Services\Session;

// ...
// ...
    if($login_valid){
        //...
        $session = new Session();
        $session->create();
    }

会话服务

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)
    }
    //...
}

在会话服务中设置数据库服务实例时会抛出错误。错误如下:

调用了 DB 的 __construct 方法,该方法采用 4 个参数(在 services.yaml 中全局定义),在会话服务中实例化 DB 服务时我没有提供这些参数。

但是,当我直接在控制器中以这种方式实例化数据库服务时,情况绝不会如此。

此外,使用 __constructservices.yaml 中设置的服务参数以避免每次都必须传递这些参数的好处之一不是吗?

Symfony 知道在调用 DB 服务时触发 __construct,并且它需要的参数就在 services.yaml 中设置 - 给出了什么?

总之你需要使用依赖注入

你是正确的,通过在 services.yml 中注册 Database class 参数,Symfony 能够在实例化期间注入这些值。但是,这仅在使用依赖项注入容器时自动完成。

您需要在 LoginControllerSession 服务中使用它。

登录控制器

namespace App\Controller

use App\Services\Session;

class LoginController
{
    private $session;

    public function __construct(Session $session)
    {
        $this->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)
    }
}