【问题标题】:Should I fully separate Models and ORM in MVC?我应该在 MVC 中完全分离模型和 ORM 吗?
【发布时间】:2012-01-01 19:24:48
【问题描述】:

我正在开发一个未使用任何框架的 PHP 中的 MVC 应用程序。我将RedBean 用于我的ORM,它实现了datamapper 模式并且工作方式与doctrine 非常相似。

根据question,我知道模型不是 ORM 对象。在我的项目中,我有以下场景:

  • 需要与数据库中大量表对话的“复杂”模型:

    • 其中一个模型可能类似于 RBAC 权限系统。控制器应该能够调用类似$permission->isAllowed($controller, $action, $resource) 的东西来确定是否允许用户执行请求的操作。此外,他可能会调用$permission->getPermissions() 来获取用户拥有的权限列表。
  • “简单”模型,其中模型通常可以由数据库中的 1 个表表示:

    • User 就是一个这样的模型。例如$user->changeRank()$user->addPoints() 等。

我现在面临的问题是,查看各种框架的大多数文档,我可以看到在示例中,控制器直接与 ORM 对话。例如,这是来自symfony2 的示例控制器:

public function createAction()
{
    $product = new Product();
    $product->setName('A Foo Bar');
    $product->setPrice('19.99');
    $product->setDescription('Lorem ipsum dolor');

    $em = $this->getDoctrine()->getEntityManager();
    $em->persist($product);
    $em->flush();

    return new Response('Created product id '.$product->getId());
}

如果 ORM 不是模型,为什么允许控制器直接与其交互?它不应该与看起来像这样的模型交互吗?

class ProductModel{
   public function newProduct($name, $price, $description){
        $product = new Product();
        $product->setName('A Foo Bar');
        $product->setPrice('19.99');
        $product->setDescription('Lorem ipsum dolor');

        $em = $this->getDoctrine()->getEntityManager();
        $em->persist($product);
        $em->flush();
   }
}

最后,我在前面概述了permissions 模型。这是否被认为是 MVC 上下文中的模型?此类将在整个应用程序中使用,因为大多数 abction 都需要检查访问权限。

【问题讨论】:

    标签: php model-view-controller orm model


    【解决方案1】:

    ORM(对象关系映射器)用于生成模型文件。模型文件用于在应用程序和数据库(模型)之间进行通信。您似乎精通 ORM 流程,但对于那些可能不熟悉的人来说,快速回顾一下(以学说为例),我可能会很幸运并回答您的问题。

    您使用 ORM 来内省您的数据库架构,从而生成一个架构文件。现在有了这个模式文件,您可以更改它以满足您的应用程序需求。例如,您可以添加actAs: { Timestampable ~}actAs: NestedSet: hasManyRoots: true。此外,您将希望使用此架构文件来设置您希望对象之间的关系如何表现(即 1:M、M:M 使用 refClass 等)

    一旦您的架构文件准备就绪,您就可以发出命令来生成模型文件。模型文件是可以在应用程序中用于访问数据库的类。因此控制器实际上是通过 ORM 生成的文件与模型(您的数据库)进行通信。

    您提供的示例是一个很好的示例,因为您可以将大部分业务逻辑从您的操作(页面控制器)中卸载到您的模型中。这样,可以从其他代码点访问相同的逻辑,而无需处理任何控制器级逻辑。教义所做的(并且推进也是如此)是允许您创建“表”(或“对等”)类。这些类充当处理多个对象的容器。您应该在这些类中添加您在第二个示例中演示的业务逻辑。

    最终目标是让您的操作尽可能轻量级,只处理请求参数和表单处理,然后通过“表格”或您设计的自定义类将值推送到您的模型。遵循此范例,您可以拥有一个功能丰富的应用程序,其中包含修剪操作和集中式业务逻辑。

    编辑---

    抱歉,我错过了您关于权限 API 的最后一个问题。从您发布的内容来看,它似乎确实遵循 MVC 范例,因为您有一个权限对象并用作控制器和数据库之间的 API。

    【讨论】:

    • 是否可以接受某些模型需要实体管理器(需要持久性的模型)来管理它们,而其他模型(可能不需要持久性)不需要实体管理器?有两种方法来实例化和管理模型对我来说似乎不是很干净。
    • @phpdev:你是专门指Doctrine吗?
    • 是的。我有一些模型根本不与数据库交互,所以它们根本不需要实体管理器。
    • @phpdev:看来entitymanager 是在学说 2.0 中引入的新 API。不幸的是,我还没有从 1.2 转换,所以我无法回答你关于 entitymanager 的问题。不过,entitymanager 似乎在理论层而不是您的模型层中,因此如果您不想要它,就不会产生 entitymanager 的开销。检查一个需要数据库访问的基本模型文件,看看它是否与不需要的基本模型文件不同。唯一的区别可能是实际的成员变量和其他一些设置选项。
    猜你喜欢
    • 2011-08-30
    • 1970-01-01
    • 2020-03-09
    • 1970-01-01
    • 2019-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-13
    相关资源
    最近更新 更多