在何处以及如何实例化依赖项

时间:2018-11-22 13:25:36

标签: php dependency-injection

在网站项目后端的范围内,我非常努力地理解依赖注入以及如何避免全局变量。在这里,我正在使用PHP。

// MySQLDatabase.php
class MySQLDatabase
{
    private $database;

    public function __construct($db_host, $db_username, $db_password, $db_name) {
        $this->database = new mysqli(
            $db_host,
            $db_username,
            $db_password,
            $db_name
        );
    }
}

// User.php
class User {
    public function __construct($database, $id);
}

// Image.php
class Image {
    public function __construct($database, $id);
}

$database = new MySQLDatabase($dbh, $dbu, $dbp, $dbn);
$existingUser = new User($database, $userID);
$existingImage = new Image($database, $imageID);

我知道,为了保持代码的可测试性,可包含性且没有全局变量,我需要注入依赖项。我很困惑的地方是 where 实例化这些依赖关系。上面的代码似乎回答了有关依赖注入的每个问题,他们说:“这就是您的方法!”但是他们从不解释如何设置程序的其余部分,以便可以将依赖项挂钩在一起。

我首先想到了使用引导程序文件,该文件首先实例化依赖项,以供程序的其余部分使用:

// bootstrap.php
$database = new MySQLDatabase($dbh, $dbu, $dbp, $dbn);

但是对我来说,这似乎是我在这里创建一个全局对象。我的几乎每个页面都需要数据库,并且这里的这个数据库将在每个脚本中传递……对我来说似乎像一个单身汉(每个人都说避免这样做)。

我可以逐页实例化数据库。这意味着user.php页面将不使用引导文件,而仅提取其所需的依赖项(数据库,用户类等)。这会在每个页面上发生(user_images.php,login.php)。但这似乎是代码重复,因为每个页面都将包含一些相同的代码。我还考虑过要创建一个静态类型的类,以使其更易于实例化数据库,您可以通过文件来加载该数据库:

// MySQLDatabase.php
class SpecificDatabase
{
    private static $initialized = false;

    public static function initialize($db_host, $db_username, $db_password, $db_name) {
        if(self::$initialized) return;
        self::$database = new MySQLDatabase(
            $db_host,
            $db_username,
            $db_password,
            $db_name
        );
        self::$initialized = true;
    }
}

但是在这种情况下,您每次需要使用数据库时都必须始终获得db凭据来初始化数据库(除非您在此处对其进行了硬编码,但是我认为这同样糟糕)。在我的代码中几乎每个页面上都有这样的东西:

require_once(__DIR__.'/vendor/autoload.php');
require_once(__DIR__.'/utilities/database/SpecificDatabase.php');
require_once(__DIR__.'/entities/User.php');

// load environment variables
$dotenv = new Dotenv\Dotenv(__DIR__);
$dotenv->load();

$database = new SpecificDatabase(getenv('DATABASE_HOST'), getenv('DATABASE_USERNAME'), getenv('DATABASE_PASSWORD'), getenv('DATABASE_NAME'));
$user = new User($database, $userID);

有人可以帮助我更好地理解这一点吗?我真的想成为一名出色的程序员。有一些障碍需要我花更多的时间来理解,我认为这可能归结为一些简单的误解,尤其是词汇上的误解-例如,我认为避免重复 AND 避免全局变量。我对依赖注入的大部分研究都是从类内部拉出依赖的结论。但是当他们被拉出时,他们会去哪里...?

0 个答案:

没有答案