【问题标题】:PHP - Injecting a Model in a Controller properlyPHP - 在控制器中正确注入模型
【发布时间】:2017-01-20 00:27:51
【问题描述】:

我有一个以这种方式工作的简单 PHP MVC 框架:

   StaticFramework (1)
          |
          V
         DIC (2)
          |
          V
     HTTPRequest
          |
          V
         App <-> Router
          |
          V
      Controller <-> Model
          |
          V
         View
          |
          V
     HTTPResponse

(1) StaticFramework 是一个静态的“前端控制器”,它通过 (2) DIC(依赖注入)为 App 提供默认依赖项Container),其工作方式类似于 Pimple。可以访问容器以更改这些默认依赖项。比如Router类被DIC注入到App中。

我这里有个问题,因为它是一个 MVC 应用程序,我有 3 个重要的层:

  • 型号;
  • 查看;
  • 控制器。

注入View 很容易,因为它只是一个具有render 方法的类,用于呈现PHP 或HTML 文件,因此我只需在我的Controller 中注入View 的一个实例。

但是在Controller 中注入Model 似乎更难。每个Model 都是一个单独的类,所以我不能像为View 那样注入它。每个Model 可能还需要其他依赖项,例如DatabaseXML 类。

此外,我无法预测 Controller 将需要哪些模型,因为它可能需要其中几个模型,例如,ArticleController 需要 ArticleModelUsersModel

我有几个解决方案:

  • Controller 中注入ModelFactory 类,这将为Controller 实例化模型。但由于每个Model 可能需要不同的依赖项,ModelFactory 必须知道它需要哪一个,这对于类似于 PimpleDIC 来说似乎是不可能的;
  • 不在Controller 中注入模型,并将它们中的每一个作为单独的类,这扩展了它们的需要。例如,如果需要 MySQL 连接,Model 应该扩展 Database。但这意味着模型紧密依赖于其父模型,这使得Model 无法使用模拟类或拥有多个数据源,例如,如果Model 需要DatabaseXML 怎么办? ?

那么,就我的框架而言,在Controller 中注入模型的最佳方法是什么?

提前感谢您的回答。

【问题讨论】:

  • 疙瘩不是 DIC 而是服务定位器
  • ^ 这是一个美化的关联数组,用作服务定位器
  • @Linus 我知道其他一些 DIC 以不同的方式工作,例如通过反射预测依赖关系等,但是 Pimple 怎么不是 DIC?此外,我知道服务定位器是一种反模式,因为它在应用程序和服务定位器之间创建了紧密耦合。但是,例如,如果你在另一个对象中注入一个Container(一个类似 Pimple 的对象),让它从上述Container 中获取它的依赖关系,它是如何创建紧密耦合的,那么反模式又是如何产生的呢?顺便说一句,谢谢您的评论。
  • @TheKitsuneWithATie 看看这个stackoverflow.com/questions/16472924/…,如果注入到对象中,任何 DI 容器都是服务定位器

标签: php model-view-controller dependency-injection dependencies inversion-of-control


【解决方案1】:

各位大神,这让我很伤心。

  • “静态框架”表示你的代码基础处于全局状态
  • pimple 不是 DI 容器
  • 你描述的不是“视图”,而是一个愚蠢的模板
  • 模型是一个层,而不是要注入的类
  • 你应该学会使用命名空间而不是滥用后缀

&lt;/rant&gt;

您的控制器应该与Services 进行交互。模型是包含持久性抽象、域实体、服务、存储库和用于描述应用程序业务逻辑的事物的整个事物。

无论如何,要使用必要的服务填充您的控制器,您应该使用适当的依赖注入器。我会推荐Auryn(基于反射)或Symfony DI(基于配置)。

【讨论】:

  • 首先,StaticFramework 不是App 工作所必需的,正如我所说,它只为其提供默认依赖项,因此StaticFramework(这更像是一个“前控制器”我认为)如果你愿意,可以完全不用。其次,我在我的真实代码中使用了命名空间,但我在这里给出了简单的类名只是为了举例。另外,我知道模型是一个层而不是一个类,但是当我在这里说“模型”时,我的意思是一个为@管理/检索数据(SQL、XML、缓存......)的类987654328@。另外,我会看看你推荐的DIC,谢谢。
  • 不管你的意思是什么,重要的是你所说的——我们都需要说一种通用的、无处不在的语言才能相互理解,还有什么比 正确方式?
【解决方案2】:

在 ASP.Net MVC 中解决此问题的方法是,请求始终被定向到控制器(而不是控制器本身)上的方法。

您示例中的应用程序将查看该方法的参数并为每个参数的类型调用特定的模型绑定器。

这在类型不安全的语言中可能会很棘手:P

【讨论】:

    猜你喜欢
    • 2012-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-29
    • 2019-07-14
    相关资源
    最近更新 更多