【问题标题】:Code Style: Doctrine2 queries from entity repository?代码风格:来自实体存储库的 Doctrine2 查询?
【发布时间】:2015-11-30 01:25:31
【问题描述】:

据我了解,最好的代码风格是将复杂的 SQL/DQL 查询放到实体存储库中。

例如,有一个名为“News”的实体。它有一个名为“NewsRepository”的自己的实体存储库。

在控制器中有这样的代码:

/**
 * @Route("/news", name="news")
 */
public function indexAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();
    $paginator = $this->get('knp_paginator');

    $news = $paginator->paginate(
        $em->createQuery('SELECT n FROM AppBundle:News n'),
        $request->query->getInt('page', 1),
        10
    );

    return $this->render('app/news/list.html.twig', array(
        'news' => $news,
    ));
}

现在我想添加更多功能(过滤、排序、..)。那是因为我认为应该将查询移至任何服务或实体存储库。但是最好的编码风格是什么?

(有没有人有很好的通用想法如何轻松添加过滤,按...排序?)

【问题讨论】:

    标签: symfony doctrine-orm coding-style entity knppaginator


    【解决方案1】:

    当然,

    如果您想再次使用它,每个请求都应该在存储库中。不仅最复杂。

    我会尝试回答你的第一个问题,然后给你一个可以帮助你“通用过滤”的提示

    如果你想把你的请求放在你的 NewsRepository 中的 repo 中:

    public function findAllOrderedByDate() {
        $qb = $this->createQueryBuilder('n');
        $qb->orderBy('creationDate');
    
        return $qb->getQuery()->getResult();
    }
    

    在你的控制器中:

    public function indexAction(Request $request)
    {
        $newsRepo = $this->get('doctrine')->getRepository('AppBundle:News');
        $em = $this->getDoctrine()->getManager();
        $paginator = $this->get('knp_paginator');
    
        $news = $newsRepo->findAllOrderedByDate();
        $pagination = $paginator->paginate(
            $news,
            $request->query->getInt('page', 1),
            10
        );
    
        return $this->render('app/news/list.html.twig', array(
            'news' => $pagination,
        ));
    }
    

    对于过滤,您的报告中有一个技巧,即返回 qb 而不是直接结果。

    同样,您可以创建一个函数,使用给定参数(使用 addOrderBy()andWhere)添加您的 orderBy,并返回 queryBuilder。毕竟,你可以处理。

    编辑:


    我在这个帖子上看到的解决方案:

    public function findAllOrderedByDate(callable $func = null) {
        $qb = $this->createQueryBuilder('n');
        $qb->orderBy('creationDate');
    
        if (is_callable($func)) {
            return $func($qb);
        }
        return $qb->getQuery()->getResult();
    }
    

    在你的控制器中:

    $func = function (QueryBuilder $qb) use ($paginator, $request) {
        return $paginator->paginate($qb, $request->query->getInt('page', 1), 10);
    };
    $pagination = $em->getRepository('AppBundle:News')->findAllOrderedByDate($func);
    

    【讨论】:

    • 一点补充:如果 getResult()/getArrayResult() 中的记录非常多 - 最好返回 queryBuilder 对象 - 分页器将查询 db 以获取所需的记录数量。
    • 这是一个很好的问题。对我来说,存储库必须返回结果。但我在thread 上阅读了一个非常有趣的解决方案。该解决方案允许您使用分页器或不使用。我会更新我的答案
    • 我说过,只是因为我有经验)) - 当结果太多时(不记得有多少,但超过 5k,并且数量每分钟都在增长 - mPOS 服务)。在这种情况下(使用分页器时)——最好的解决方案是传递 queryBuilder 对象——因为分页器会运行带有所需限制和偏移量的结果查询。
    • 是的,不值得检索所有表演条目。我更新了我的答案。告诉我它是否对你有好处。
    • 即使第一个答案也很好!)我刚刚提到了一件可能会导致问题的事情。
    【解决方案2】:

    模型零件必须在模型零件中。将查询移至仓库。 你是什​​么意思,这样说:“很好的通用想法如何轻松添加过滤,按顺序排列”?
    OrderBy
    Where - 相同链接

    【讨论】:

      猜你喜欢
      • 2012-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-20
      • 2012-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多