Symfony2 - 重构代码/方法的最佳实践?

时间:2014-03-31 09:59:11

标签: symfony methods refactoring

我在我的控制器中使用搜索代码和分页代码,不用说重复代码就是编码习惯不好。那就是说Symfony2中最好的做法是什么,以避免在我的所有控制器中重复代码?

如果重新考虑了代码,我该如何访问?

控制器

// Search code
    $results = null;
    $query = $request->query->get('q');

    if (!empty($query)) {
        $em = $this->getDoctrine()->getManager();

        $results = $em->createQueryBuilder()
            ->from('AcmeDemoBundle:Blog', 'b')
            ->select('b')
            ->where('b.title LIKE :search')
            ->setParameter(':search', "%${query}%")
            ->getQuery()
            ->getResult();
    }


    // Pagination code
    $page = $request->get('page');

    $count_per_page = 5;
    $total_count = $this->getTotalBlogs();
    $total_pages = ceil($total_count/$count_per_page);

    if (!is_numeric($page)) {
        $page = 1;
    } else {
        $page = floor($page);
    }

    if ($total_count <= $count_per_page) {
        $page = 1;
    }

    if (($page * $count_per_page) > $total_count) {
        $page = $total_pages;
    }

    $offset = 0;

    if ($page > 1) {
        $offset = $count_per_page * ($page - 1);
    }

    $em = $this->getDoctrine()->getManager();

    $blogQuery = $em->createQueryBuilder()
        ->select('b')
        ->from('AcmeDemoBundle:Blog', 'b')
        ->addOrderBy('b.created', 'DESC')
        ->setFirstResult($offset)
        ->setMaxResults($count_per_page);

    $blogFinalQuery = $blogQuery->getQuery();

    $blogPage = $blogFinalQuery->getArrayResult();

    foreach ($blogPage as $blog) {
        $blog_id = $blog['id'];
        $commentRepository = $this->getDoctrine()
            ->getRepository('AcmeDemoBundle:Comment');

        $comments[] = $commentRepository->findByBlog($blog_id);
    }

// exit(\ Doctrine \ Common \ Util \ Debug :: dump($ comments));

    return $this->render('AcmeDemoBundlBundle:Default:index.html.twig', array(
        'blogPage'     => $blogPage,
        'total_pages'  => $total_pages,
        'current_page' => $page,
        'comments'     => $comments,
        'query'        => $query,
        'results'      => $results,

    ));

1 个答案:

答案 0 :(得分:1)

首先,您可以将所有自定义查询都放在custom repository classes中。我怀疑这将覆盖你在这种情况下所需的所有重复使用。

例如,在AcmeDemoBundle:Repository中创建一个BlogRepository类,并按如下方式注释Blog实体类以定义它的存储库类:

/**
 * @ORM\Entity(repositoryClass="Acme\DemoBundle\Repository\BlogRepository")
 */

然后在存储库中为每个需要的自定义查询添加方法,同时牢记通常命名存储库方法的方式。看起来控制器方法getTotalBlogs()也可能是BogRepository上的一个方法,例如:

    public function findFiltered($page, $count_per_page = 5, $filterText = '')
    {
        $total_count = $this->findTotal();
        // Code to initialise page and offset here

        $queryBuilder = $this->createQueryBuilder('blog');
        $queryBuilder->...
        ...
    }

请注意,如果没有传入$ filterText,则可以使用上述方法获取所有博客。您只需要这样的内容:

    if (!empty($filterText))
    {
        queryBuilder->where('b.title LIKE :search')
                    ->setParameter(':search', "%${query}%")
    }

然后,可以使用方法创建CommentRepository,以查找给定博客(id)集的所有注释。请注意,您可以使用sql'IN'子句使用单个查询获取所有注释:

    $commentQuery = $em->createQueryBuilder()
                       ->select('comment')
                       ->from('AcmeDemoBundle:Comment', 'comment')
                       ->where('comment.blog IN (:ids)')
                       ->setParameter('ids', $blogIds);

除了自定义存储库类,我还使用管理器服务(例如BlogManager)来封装业务流程。我的控制器主要使用管理器而不是直接使用存储库,但这取决于功能。

我有点困惑,你有一个整体结果查询只返回博客,其中标题就像搜索文本,而分页查询返回(一页)所有博客。那可能只是因为您的代码正在进行中?