PHP路由器/调度程序,依赖注入,传递依赖项

时间:2013-06-24 19:30:36

标签: php dependency-injection

所以我正在创建自己的小框架来学习设计模式,我认为我有一个不错的Router / Dispatcher框架,我正在编写一个小的MVC框架来处理请求。我的R / D看起来像这样:

$router = new Router();
$dispatcher = new Dispatcher();
$request = new Request();
$response = new Response();
$router->addRoute(new Route('user', 'view', 'UserController'));

$route = $router->route($request, $response);
$dispatcher->dispatch($route, $request);

现在我的模型对象可以从几个不同的数据源(mysql,oracle)中提取数据,因此我试图找出将实例化数据源传递给这些对象而不耦合它们的最佳方法。在一个相关的问题中,我指出了使用DIC的方向,但我仍然不确定在何处实例化它以及如何让我的模型对象访问它。关于如何解耦事情,我也有点模糊。我目前对使用DIC的理解是添加如下内容:

$oic = new IOC();
$oic->register('mysql_db', new DBMysql(...));
$oic->register('oracle_db', new DBOracle(...));

class UserController
{
    public function execute()
    {
        $user = User::fetch($oic->get('mysql_db'), $user_id);
        ...
    }
}

通过这个例子,我仍然模糊如何从创建到控制器执行$ oic。它似乎也太紧密耦合了。例如,如果我有100个不同的控制器引用mysql_db并且我想将它们切换到不同的数据源,那么我将使用相同的信息更新100个控制器类。

我正在考虑更改我的路由器路由以接受db参数,但是如果我有一个控制器需要引用多个数据库连接(我会)。

更新

我最后只是改变我的路由器路由以将参数传递给控制器​​,所以在我粗略的例子中,如果我将用户信息存储在MySQL数据库中,但用户的部门信息存储在Oracle数据库中,它看起来像这样:

$db_mysql = new DBMysql();
$db_oracle = new DBOracle();
...
$router->addRoute(new Route('user', 'view', 'UserController', array($db_mysql, $db_oracle)));
...
class UserController
{
    private $db_user = null;
    private $db_dept = null;

    public function __construct(DBInterface $db_user, DBInterface $db_dept)
    {
        $this->db_user = $db_user;
        $this->db_dept = $db_dept;
    }

    public function execute()
    {
        $user = User::fetch($this->db_user, $user_id);
        $dept = Dept::fetch($this->db_dept, $user->dept_id);
    }
}

1 个答案:

答案 0 :(得分:1)

不要注入容器,这会引导您进入另一种服务定位器模式。

这被认为是反模式,因为您的代码(控制器)将取决于容器。

如果您在控制器中想要DBObject,请注入DBObject

// Configuration of your application
$oic = new IOC();
$oic->register('db', new DBMysql(...));
// or
// $oic->register('db', new DBOracle(...));

// Controller
class UserController
{
    private $db;

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

    public function execute()
    {
        $user = User::fetch($this->db, $user_id);
        ...
    }
}

通过这种设计,控制器不关心它将使用什么数据库实现(oracle或mysql)。它可以在应用程序的“配置”部分进行更改。


现在要将db对象注入控制器,您有几种可能性。

我建议您查看现有的DI容器,例如Symfony或PHP-DI(免责声明:我正在研究那个容器)。

基本上,它们允许您定义UserController::__construct

参数中应该给出的内容