【问题标题】:How do I fetch the PHP DI container?如何获取 PHP DI 容器?
【发布时间】:2019-01-13 10:51:38
【问题描述】:

如何使用PHP DI 加载数据库容器? 这是迄今为止我尝试过的变体之一。

设置.php

<?php 
use MyApp\Core\Database;
use MyApp\Models\SystemUser;

return [
    'Database'      => new Database(), 
    'SystemUser'    => new SystemUser()
];

init.php

$containerBuilder   = new \DI\ContainerBuilder(); 
$containerBuilder->addDefinitions('Settings.php');
$container          = $containerBuilder->build();

SystemUserDetails.php

<?php 
namespace MyApp\Models\SystemUser;

use MyApp\Core\Database;
use MyApp\Core\Config;
use MyApp\Helpers\Session;


/**
 *
 *  System User Details Class
 *
 */
class SystemUserDetails 
{

/*=================================
=            Variables            =
=================================*/

    private $db;


/*===============================
=            Methods            =
================================*/

    /**
     *
     *  Construct
     *
     */
    public function __construct(Database $db)
    {
        # Get database instance
        // $this->db           = Database::getInstance();
        $this->db           = $db;
    }


    /**

MyApp\Models\SystemUser\SystemUserDetails::__construct() 函数的参数太少,在第 54 行的 /www/myapp/models/SystemUser.php 中传递了 0,而预期正好是 1 文件:/www/myapp/models/SystemUser/SystemUserDetails.php

数据库不应该自动加载吗?

追踪:

  1. 目前,我的主要index.php 文件扩展了init.php,这是它创建容器的文件(在帖子中粘贴了代码部分)。

  2. 然后我调用 App 类,它获取 URL(mysite.com/login/user_login) 并实例化一个新的控制器类并运行上述方法,在本例中,它是第一页 - MyApp/Contollers/Login.php

    1. user_login 方法获取凭据,验证它们,如果它们有效,则使用 SystemUser 对象登录。

SystemUser 类:

namespace MyApp\Models;


class SystemUser
{

    public $id;

    # @obj SystemUser profile information (fullname, email, last_login, profile picture, etc')
    protected $systemUserDetatils;


    public function __construct($systemUserId = NULL)
    {
        # Create systemUserDedatils obj
        $this->systemUserDetatils   = new \MyApp\Models\SystemUser\SystemUserDetails();

        # If system_user passed
        if ( $systemUserId ) {

            # Set system user ID
            $this->id                   = $systemUserId;

            # Get SysUser data
            $this->systemUserDetatils->get($this);

        } else {

            # Check for sysUser id in the session:
            $systemUserId                   = $this->systemUserDetatils->getUserFromSession();

            # Get user data from session 
            if ( $systemUserId ) {

                # Set system user ID
                $this->id                   = $systemUserId;

                # Get SysUser data
                $this->systemUserDetatils->get($this);
            }
        }
    }
}

【问题讨论】:

  • 它看起来像 SystemUser 类扩展 SystemUserDetails 根据构造函数需要一个数据库实例作为参数,尝试将数据库实例作为参数传递给 SystemUser 类,看看它是否有效
  • @Shahin 为什么你相信SystemUser 扩展了SystemUserDetails?你从哪里得到的?
  • @Shahin 是对的,但这不是假设通过将 DB 类注入我想要的任何类来直接工作吗?我可能对依赖注入不了解的地方在哪里,希望得到解释。
  • @yivi 我没有显示什么?你想看什么,我没有问题可以添加到我的帖子中..
  • 是否需要运行$userManager = $container-&gt;get('SystemUserDetails');才能获得

标签: php oop dependency-injection containers php-di


【解决方案1】:

PHP-DI 工作正常。

在你的SystemUser 课程中你正在做:

$this->systemUserDetatils   = new \MyApp\Models\SystemUser\SystemUserDetails();

SystemUserDetails 的构造函数需要一个 Database 对象,您没有传递该对象。

通过直接调用new您没有使用 PHP-DI。通过这样做,你隐藏依赖,如果你想使用依赖注入系统,这正是你应该试图避免的。

如果SystemUser 依赖(“需要”)SystemUserDetails,则依赖项应该是显式的(例如,在其构造函数中声明)。

此外:对于这样的系统,您不需要定义文件。而且您在问题中显示的定义文件不遵循the best practices recommended by PHP-DI

你的设计远非完美,我不确定你的最终目标,但如果你这样做,它可能会奏效:

<?php
// src/Database.php

class Database {
    public function getDb() : string {
        return 'veryDb';
    }
}
<?php
// src/SystemUserDetails.php

class SystemUserDetails {

    protected $db;

    public function __construct(Database $db)
    {
        $this->db           = $db;
    }

    public function getDetails() {
       return "Got details using " . $this->db->getDb() . '.';
    }
}
<?php
// src/SystemUser.php
class SystemUser {

    protected $details;

    public function __construct(SystemUserDetails $details, $userId=null) {

        $this->details = $details;
    }

    public function getUser() {
       return "Found User. " .$this->details->getDetails();
    }
}
<?php
//init.php
require_once('vendor/autoload.php');

// build the container. notice I do not use a definition file.
$containerBuilder   = new \DI\ContainerBuilder();
$container          = $containerBuilder->build();

// get SystemUser instance from the container.
$userInstance = $container->get('SystemUser');

echo $userInstance->getUser(), "\n";

结果:

Found User. Got details using veryDb.

【讨论】:

  • 不,你很困惑。 SystemUser 类使用 SystemUserDetails 类。 SystemUser 是主要的 SystemUser 类。
  • 我很抱歉,但我不相信我很困惑。我在看你的代码。 SystemUser 使用 SystemUserDetails,但没有在任何地方声明该依赖项。您正在尝试直接实例化 SystemUserDetails,而不注入正确的依赖项。
  • @Rick 试试我的代码,你会发现它有效。问题是你直接调用new绕过了DI层。
  • 同样让Settings.php 包含new Database() 是错误的,这意味着您直接在配置中创建Database 实例,而不是让PHP-DI 创建它并知道它。再次阅读php-di.org/doc/php-definitions.html#values
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-18
  • 1970-01-01
  • 2012-04-16
  • 2012-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多