Php 关于我的模型层方法的反馈Symfony 2模型层+;教条
请就以下创建模型层的方法提供反馈,该模型层由业务规则组成,这些规则将数据访问的原则统一起来 我当前的方法基于这样一个概念,即模型是一个ContainerWare类/对象,所有非库的、特定于业务的域逻辑都在其中 我发现我必须敲打框架才能这样做,这就是为什么我大脑的一部分质疑我的方法 我目前正在使用Symfony 2,它与所有现代PHP MVC框架一样,使用了类似Doctrine 2的ORM层,并且不可避免地将其视为模型层。我猜情况与ZF2类似,因此尽管我的示例是用SF2编写的,但将其视为框架不可知的问题 具体例子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编写的,但将其视为框架不可知
作为一个具体的例子,考虑下面的场景:
信息要求- 作为用户,我可以创建属于我的消息
- 作为用户,我可以更新属于我的消息
- 作为用户,我可以归档属于我的邮件
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);
}