symfony 2中的代码分离 - Controller与Service vs实体

Abd*_*el5 6 model-view-controller symfony

我正在使用symfony 2,我对代码分离有疑问.我想确保我正确理解控制器中应该包含哪些元素,服务中的内容以及实体中的内容.

让我们想象一下,我有需要显示的文档列表.在显示之前的每个文档上,我还必须执行一些逻辑操作(例如,添加两个变量).

理解实体类只关注单个实体上的数据检索和操作.我不应该输入任何自定义代码.据我所知,这应该由服务完成.

但我应该:


  • 在执行所需逻辑后,使用服务根据某些条件传递到控制器文档列表,
  • 或者使用控制器下载文档列表,然后将文档传递给服务以执行某些逻辑?

我宁愿认为第一种方法适合保持控制器薄(瘦控制器,大型模型),但这种方法是否合适?实体中应该有什么代码,控制器中有什么代码?服务中有什么代码?

特别是我应该在哪里与实体经理相关 - 在控制器中还是在服务中?

让我们假装在我的应用程序的许多地方我需要检查文档是否已完成,然后才允许用户执行任何操作(例如编辑它).这绝对应该是在服务中,因为需要另一个服务来检查这个.但是,我是否应该将文档实体对象加载到控制器中,将其发送到服务以验证它是否可以最终确定,或者更确切地说是在服务中加载文档并执行检查?

Mat*_* G. 9

我的Symfony 2架构是(使用Doctrine ORM):

  1. 仅具有路由逻辑的精简控制器
  2. 每个实体的服务(又名"经理")(所有业务逻辑都在这里)
  3. 为我的其他需求定制服务(即使用Amazon S3或Mandrill邮件系统等外部工具)
  4. 每个实体的存储库(只是从数据库中读取实体的方法)

控制器内的每个动作都从实体的管理器调用一个或多个方法; 我总是试图避免直接使用存储库的"魔术方法"来支持自定义方法:在操作中,而不是调用

$this->getDoctrine()->getRepository(<entity>)->findBy(array('parent' => null));
Run Code Online (Sandbox Code Playgroud)

我在存储库中创建了这个方法:

public function findParents()
{
    return $this->findBy(array('parent' => null));
}
Run Code Online (Sandbox Code Playgroud)

在我使用的动作中:

$this->getDoctrine()->getRepository(<entity>)->findParents();
Run Code Online (Sandbox Code Playgroud)

当然,这是一个简单的例子,但它适用于更复杂findBy或更复杂的findOneBy问题.

  • 完成:我扩展了我的例子:) (2认同)

Abs*_*dés 7

在Symfony2中,使用存储库和服务是超级简单的解耦逻辑.例如:

具有aditional自定义查找程序的实体存储库

use Doctrine\ORM\EntityRepository;

class MyEntityRepository extends EntityRepository
{
    public function findAllWithX($parameter)
    {
         // your DQL. manipule own data. filters.
    }
}
Run Code Online (Sandbox Code Playgroud)

处理主要业务逻辑的胖服务

// could be a listener 
class MyFatService 
{
    public function __construct(MyEntityRepository $mer,
                                AnotherRepository $aor,
                                MisteriousService $mis)
    {
        $this->mer = $mer;
        $this->aor = $aor;
        $this->mis = $mis;
    }

    public function someBigAction($paramX, $paramY)
    {
         $foo = $this->mer->findAllWithX($paramX);
         $bar = $this->aor->findBy(....);

         // manipule data. complex operations. 
         // call related services. 
         // manipule data related to many repositories
    }
}
Run Code Online (Sandbox Code Playgroud)

要定义服务:

services:
    my_entity_repository:
        class: AppBundle\Repository\MyEntityRepository
        factory: [@doctrine, getRepository]
        arguments:
            - %entity.my_entity%

    my_another_repository:
        class: AppBundle\Repository\AnotherRepository
        factory: [@doctrine, getRepository]
        arguments:
            - %entity.my_another_entity% 

    my_fat_service:
        class: AppBundle\MyFatService
        arguments:
            - @my_entity_repository
            - @my_another_repository
            - @misterious_service
Run Code Online (Sandbox Code Playgroud)

在你的控制器中:

public function blaAction($x, $y)
{
   // leave the heavy work to services. 
   // just handle request and send the response
   $data = $this->get('my_fat_service')
                ->someBigAction($x, $y);

   return $this->render('template.twig', ['data' => $data]);
}
Run Code Online (Sandbox Code Playgroud)

ps:对不起我的英语