2

所以我正在创建自己的小框架来学习设计模式,并且我认为我已经有了一个不错的 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 参数,但是如果我有一个需要引用多个 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);
    }
}
4

1 回答 1

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.

于 2013-07-09T10:07:07.223 回答