0

我正在用 PHP 构建一个简单的 MVC 框架,但我被困在我必须创建一个BaseController类的部分。

每个“页面”控制器都需要从 this 扩展BaseController。因为这个 BaseController 类将具有允许用户访问template引擎和Logger类(以及其他一些东西)的属性。

我遇到的问题是我不确定如何在 BaseController 类中实例化这些东西。我显然可以__constructo()像这样对其进行硬编码:

class BaseController
{
    protected $view;
    protected $log;

    public function __construct()
    {
        $this->view = new \namespace\view('param1', 'param2');
        $this->log = new Logger('name');
        $this->log->pushHandler(new StreamHandler('path/to/your.log', Logger::WARNING));
    }
}

但这并不能使它非常模块化。例如,很难更改 Logger 类。或者如果用户想将模板引擎更改为 Smarty。

我也不能真正使用依赖注入的形式。因为从 扩展的每个控制器BaseController都必须将这些实例传递给BaseController.

看起来像这样:

class BaseController
{
    protected $view;
    protected $log;

    public function __construct($view, $log)
    {
        $this->view = $view;
        $this->log = $log;
    }
}

家庭控制器

class HomeController extends BaseController
{
    public function __construct($view, $log)
    {
        parent::__construct($view, $log);

        // Do my own stuff
    }
}

对我来说,当用户只想在__constructor. 甚至没有IoC

所以我现在唯一能想到的Service Provider就是__constructBaseController. 但我不确定这是否是要走的路?也许有更好的选择?

那么解决这个问题的好方法是什么?

PS。如果我确实需要 a Service Locator,那里有什么好的例子吗?我发现的那些是由似乎他们并不真正知道他们在说什么的人写的。他们基本上是在抄袭彼此的博文。

4

1 回答 1

1

您首先需要考虑什么是控制器的职责,为什么它需要访问日志功能,或者它为什么要设置模板引擎或切换模板?

控制器的工作只是从请求中提取数据(主要是表单数据/用户输入)并通过服务将其发送到模型层,它不应该选择模板,这就是视图工作。

您显然希望将基本控制器的依赖项保持在最低限度,以便在实例化子控制器时没有大量依赖项要注入。

我的基本控制器有两个依赖项,请求对象和视图都被注入。控制器简单轻巧,不应该发生任何逻辑或任何花哨的事情。曾经我不得不在我的一个控制器中使用记录器,但这只是因为 PayPal 使用 IPN 系统向它发送请求,我需要将请求中的所有数据记录到文件中以查看发生了什么,除了像这样的特殊情况,我看不出为什么控制器需要记录器。在这种情况下,只有处理 PayPal 请求的控制器拥有一个记录器实例,而不是父基本控制器。

您应该始终注入您的依赖项。不要在构造函数中实例化对象,它会使你的类与这些对象紧密耦合。

如果您最终使用服务定位器,则可能表明您的类违反了 OOP 的单一职责原则。

控制器应该很简单,不要通过添加您认为它们将来可能需要的依赖项来过度复杂化它们,尤其是对于基本控制器,否则您可能需要进行大量重构。

于 2014-03-15T15:31:18.427 回答