Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 关于我的模型层方法的反馈Symfony 2模型层+;教条_Php_Oop_Zend Framework_Symfony_Doctrine Orm - Fatal编程技术网

Php 关于我的模型层方法的反馈Symfony 2模型层+;教条

Php 关于我的模型层方法的反馈Symfony 2模型层+;教条,php,oop,zend-framework,symfony,doctrine-orm,Php,Oop,Zend Framework,Symfony,Doctrine Orm,请就以下创建模型层的方法提供反馈,该模型层由业务规则组成,这些规则将数据访问的原则统一起来 我当前的方法基于这样一个概念,即模型是一个ContainerWare类/对象,所有非库的、特定于业务的域逻辑都在其中 我发现我必须敲打框架才能这样做,这就是为什么我大脑的一部分质疑我的方法 我目前正在使用Symfony 2,它与所有现代PHP MVC框架一样,使用了类似Doctrine 2的ORM层,并且不可避免地将其视为模型层。我猜情况与ZF2类似,因此尽管我的示例是用SF2编写的,但将其视为框架不可知

请就以下创建模型层的方法提供反馈,该模型层由业务规则组成,这些规则将数据访问的原则统一起来

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

我发现我必须敲打框架才能这样做,这就是为什么我大脑的一部分质疑我的方法

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

具体例子

作为一个具体的例子,考虑下面的场景:

信息要求

  • 作为用户,我可以创建属于我的消息
  • 作为用户,我可以更新属于我的消息
  • 作为用户,我可以归档属于我的邮件
控制器

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

模型

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

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.
     }
}
经修订的控制器

我修改后的控制器现在将如下所示:

 // 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);
    // ...
}
另外两个需求也将在模型上实现

简而言之,我的方法

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

  • 控制器逻辑更少
  • 视图保持不变
  • 模型-支持容器,包含所有业务逻辑,作为数据访问访问原则
  • ORM-视为模型层的一部分,但不视为模型层
  • 服务层-需要时,我可以使用服务层处理多个层,但我发现,由于我必须构建的应用程序的简单性质,我只在少数情况下使用过它
我的问题

  • 我的方法与其他人的做法一致吗
  • 我是不是错过了一些显而易见的东西
  • 你有没有试过类似的方法,发现它好/坏
提前感谢。

首先,您可以使用简化控制器。如果找不到实体,将自动引发异常

我会调用消息方法
archive
restore
,但这是一个偏好问题

集成安全检查的好方法是由提供的。用于检查是否允许当前用户存档邮件

您的
消息模型
类似于您可以在FOSUserBundle中找到的
管理器
(即条令ODM/ORM)模式

这些管理器正在构建存储层和控制器之间的桥梁,并且都共享相同的接口(即)。通过这种方式,你可以轻松地与propel交换,即教义

通过将控制器转变为服务并注入
Manager
服务而不是注入整个容器(即通过扩展
Symfony\Bundle\FrameworkBundle\controller\controller
)并从中获取它来改进

您应该只将所需的依赖项注入到服务中,以简化测试。 在orm/odm的示例中,管理器服务将检索classname参数、entity-/documentmanager服务和存储库服务。()

您可以在Benjamin Eberley的博客文章“”中找到创建控制器实用程序服务的其他灵感

另一种常用的技术是为最常用的控制器依赖项创建抽象。()

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

当使用视图响应监听器时,您甚至可以在方法末尾使用
return
,这种监听器会自动假设您在返回原始参数,如果该方法不返回任何内容,请阅读

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

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

manager->update()
方法的行为与我的示例中的方法类似。

感谢您花时间为SF2提供建议。为清晰起见,我在这里声明MessageModel(以及该层中的其他类/对象)不仅仅是控制器和ORM之间的桥梁。我更多地将其视为业务逻辑的表示。因此,除了调用必要的模型方法来根据请求的操作执行之外,控制器所做的很少。我已经消化了您的答案,并且同意除一个之外的所有答案。关于将控制器转换为服务,您可能为一些模拟解耦增加了很多复杂性。虽然控制器(作为一项服务)在依赖性方面更为具体,但这种具体程度是有代价的:时间。对于未来的读者,我建议您使用扩展控制器基类的默认路径,然后根据您(如果您曾经)的需要将其作为服务扩展到控制器。再次感谢@nifr提供的宝贵建议。
/** 
 * @PreAuthorize("hasPermission(#message, 'ARCHIVE')")
 */
public function archiveAction(Message $message) 
{
    $message->archive();
    $this->messageManager->update($message, true);
}