php - 对我的模型层方法的反馈 Symfony 2 模型层 + Doctrine

标签 php oop zend-framework symfony doctrine-orm

请就以下创建模型层的方法提供反馈,该模型层由使用 Doctrine 进行数据访问的业务规则组成。

我目前的方法基于模型是一个 ContainerAware 类/对象的概念,所有非库、特定于业务的域逻辑都在其中。

我发现我必须锤炼框架才能以这种方式做事,这就是为什么我的一部分大脑质疑我的方法。

我目前正在使用 Symfony 2,它与所有现代 PHP MVC 框架一样,使用像 Doctrine 2 这样的 ORM 层,并且不可避免地将其视为模型层。我猜 ZF2 的情况会类似,所以尽管我的示例是用 SF2 编写的,但请将其视为与框架无关的问题。

具体示例

作为具体示例,请考虑以下场景:

消息要求

  • 作为用户,我可以创建属于我的消息。
  • 作为用户,我可以更新属于我的消息。
  • 作为用户,我可以存档属于我的消息。

Controller

在 Symfony2 中,这些要求被编码为 Controller 层中的操作。 我将跳过检查消息是否真正属于用户的无关代码,但显然,这也应该是域逻辑的一部分。在方法“belongsToUser”或类似方法中。

 // Vendor\MessageBundle\DefaultController 
 public function archiveAction(Request $request) {
    // ... 
    $em = $this->getDoctrine()
               ->getManager();
    $message = $em->getRepository('MessageBundle:Message');
                    ->getManager()
                    ->getRepository('MessageBundle:Message')
                    ->find($request->get('id'));
    $message->setIsArchived(true);
    $em->persist($entity);
    $em->flush();
    $this->flashMessage('Message has been archived.');
    // ...
}

模型

如果我要将其放入模型中,它将如下所示:

class MessageModel 
{
     public function archive($messageId) {
     // ... 
        $em = $this->getDoctrine()
                   ->getManager();
        $message = $em->getRepository('MessageBundle:Message')
                    ->find($messageId);
        $message->setIsArchived(true);
        $em->persist($entity);
        $em->flush();
     // ... return true on success, false on fail.
     }
}

修订后的 Controller

我修改后的 Controller 现在看起来像这样:

 // Vendor\MessageBundle\DefaultController 
 public function archiveAction(Request $request) {
    // ... 
    $model = new MessageModel(); // or a factory.
    $result = $model->archive($request->get('id'));
    if($result) {
        $this->flashMessage('Message has been archived.');
    } else { 
        $this->flashMessage('Message could not be archived due to a system error.');
    }
    return array('result'=>$result);
    // ...
}

其他两个要求也将在模型上实现。

我的方法简而言之

简而言之,这是我目前的做法:

  • Controller - 逻辑较少
  • View - 保持不变
  • 模型 - 容器感知并容纳所有业务逻辑,访问 Doctrine 作为数据访问。
  • ORM - 被视为模型层的一部分,但不被视为模型层。
  • 服务层 - 需要时,我可以使用服务层来处理多个层,但我发现由于简单,我只在少数情况下不得不使用它我必须构建的应用程序的性质。

我的问题

  • 我的方法与其他人的做法一致吗?
  • 我是否漏掉了一些非常明显的东西?
  • 您是否尝试过类似的东西并发现它好/坏?

提前谢谢你。

最佳答案

首先你可以使用ParamConverter来简化你的 Controller 。如果找不到实体,则会自动抛出异常。

我会调用消息方法 archiverestore 但这是一个偏好问题。

JMSSecurityExtraBundle 提供了一种集成安全检查的好方法.使用 ACLs检查是否允许您当前的用户存档消息。

您的 MessageModel 类似于您可以在 FOSUserBundle 中找到的 Manager(interface/abstract 和即学说 ODM/ORM implementation)模式。

这些管理器正在存储层和 Controller 之间架起桥梁,并且都共享相同的接口(interface)(即 UserManagerInterface )。这样你就可以轻松地交换学说和推进。

通过将你的 Controller 变成一个服务并注入(inject)你的 Manager 服务而不是注入(inject)整个容器来改进(即通过扩展 Symfony\Bundle\FrameworkBundle\Controller\Controller)并从那里获取它。

您应该只将需要的依赖项注入(inject)到您的服务中以简化测试。 在 doctrine orm/odm 的示例中,管理器服务将检索类名参数、实体/文档管理器服务和存储库服务。 ( service definition )

您可以在 Benjamin Eberlei 的博客文章“Extending Symfony2: Controller Utilities”中找到创建 Controller 实用程序服务的更多灵感。

另一种常用的技术是创建一个摘要 parent service对于您最常用的 Controller 依赖项。 ( example )

我的最后一个快速提示是将 flashmessages 的创建移动到 event listeners/subscribers .只需检查该方法是否返回类型为 Message 或更好的 MessageInterface 的对象,并添加成功提示。如果未找到该实体,您可以捕获异常并添加带有错误消息的闪现消息。

当使用像 FOSRestBundle's 这样的 View 响应监听器时,您甚至可以在方法末尾省略 return如果该方法不返回任何内容,它会自动假定您返回原始参数 - 阅读它 here .

最后,您可以在一个可很好测试的 Controller 服务中得到一个方法,如下所示:

/** 
 * @PreAuthorize("hasPermission(#message, 'ARCHIVE')")
 */
public function archiveAction(Message $message) 
{
    $message->archive();
    $this->messageManager->update($message, true);
}

manager->update() 方法的行为类似于 FOS\UserBundle\Doctrine\UserManager 中的方法。在我的示例中。

关于php - 对我的模型层方法的反馈 Symfony 2 模型层 + Doctrine,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19847141/

相关文章:

mysql - 在数据库中保存树数据(家谱)

PHP MySQL应用程序运行本地网络并在线更新数据服务器

php - 如何使用 Guzzle 更新 Woocommerce Order API

ruby - 我是否正确理解了 Ruby 中的对象?

php - 使用 Zend Framework 1.6.2 添加二阶字段时出现不明确错误

zend-framework - Zend框架中的sql问题

php - 使用 PHP 获取并比较 MySQL 的平均值

php - 为mysql数据添加前缀

javascript - JavaScript 中的 "Friend Classes"

iphone - 过程代码,vs oopy 代码和性能