模型或控制器中的动态 SQL


Dynamic SQL in Model or Controller

我知道所有的逻辑等都应该进入控制器,但我有一个SQL语句,其中的某些部分由另一个函数的返回值决定。

在我的模型中:

    $cols = 'products.id, name, currencies.symbol, basePrice';
    $m = new AuthController();
    if($m->moduleExists('Sales'))
    {
      $cols .= 'lastSold';
    }

还是在我的控制器中,并将SQL作为参数传递给模型?

    $cols = 'products.id, name, currencies.symbol, basePrice';
    if($this->moduleExists('Sales'))
    {
      $cols .= 'lastSold';
    }

tldr; version

考虑到关注点和解耦的分离,与持久性相关的代码最好地不应包含与特定系统的子模块相关的业务逻辑(无论该逻辑属于模型部分、MVC 或控制器部分的控制器,还是程序员引入系统的任何其他部分)。应避免从持久层访问业务逻辑以保持解耦,相反,应首选访问持久层的业务逻辑。

理由

在您的模型中,您应该放置与您的视图显示的内容无关的代码,即模块是否存在或是否授权拥有这样的模块。模型中的代码应该可供子系统、其他系统、独立于您的视图的任何内容甚至与特定用例相关的业务逻辑使用。它应该具有与系统范围相关的逻辑。尽管授权似乎具有系统范围,但应格外小心地处理,因为它可能会导致设计脆弱。将其放在控制器级别会更灵活。想象一下,尝试支持多种授权技术。

根据授权或查看条件来修改查询将无法维护稳定的独立模型。

所以是的,它应该进入您的控制器。

控制器无论是与视图相关的控制器还是与特定

业务逻辑相关的控制器(用例相关或系统相关,即授权控制器),现在都可以具有更改查询的授权标准,并且将来可能会出现一些与特定用例或子系统域相关的其他标准。这意味着控制器可能会更改,您甚至可以引入不同的控制器以特定方式访问同一模型。

实现

关于您的问题有很多方法。如

  • 从持久性层检索数据的完整版本,即所有列,并让您的控制器根据逻辑(即用户授权)决定显示的内容
  • 在持久性层中有多个独立于其他逻辑的查询,即查询产品、查询产品总计、查询产品与最后销售日期,然后让业务逻辑控制器决定调用哪个
  • 在持久性层中创建一个通用函数,接受 col(如果可能,非魔术值),以便根据其他控制器具有的逻辑参数化可以查看的内容并相应地调用此函数
  • 通常,最好避免将SQL查询放在不同的地方,因为维护变得困难。但是,在某些情况下可能会发生这种情况,并且在很大程度上取决于系统的设计,即业务控制器具有每个用例的自定义查询,这些查询调用持久性层以执行。