문제

I'm using a search code and pagination code in my controller(s), it goes without saying it's bad coding habits by repeating code. That being said what is the best practice in Symfony2, to avoid repeating code in all my controllers?

And how do I access the code once it's been re-factored?

Controller

// 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,

    ));
도움이 되었습니까?

해결책

For a start, you can put all your custom queries in custom repository classes. I suspect that would cover all the re-use you need in this case.

For example, create a BlogRepository class in AcmeDemoBundle:Repository and annotate the Blog entity class as follows to define it's repository class:

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

Then add methods to the repository for each custom query that's needed, bearing in mind the way that repository methods are typically named. It looks as though the controller method getTotalBlogs() could also be a method on BogRepository e.g.:

    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->...
        ...
    }

Note that the above method could be used to get all the blogs if no $filterText is passed in. You would just need something like this:

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

Then, a CommentRepository could be created with a method to find all the comments for a given set of blog(id)s. Note you could use a sql 'IN' clause to get all the comments using a single query:

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

In addition to custom repository classes I use manager services (e.g. BlogManager) to encapsulate business processes. My controllers mainly use the managers rather than using the repositories directly but it depends on the functionality.

I'm a little confused that you have an overall results query which only returns Blogs where the title is like the search text whilst the paged query returns (a page of) all blogs. That may just be a because your code is in progress?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top