在Symfony2中获取控制器操作中的项列表的最佳实践。见下面的例子

时间:2015-12-14 18:26:08

标签: php api rest symfony

我开始使用Symfony2框架创建RESTFul API。它将仅以JSON格式返回数据。我试图在动作控制器中创建一个返回用户列表的方法。问题是我的代码太多而且不优雅。我认为我做错了,因为简单的SQL查询会比我的代码更简短,更清晰。

我的方法应该从URL获取4个输入参数:limit,offset,sort field和sort direction。输出应该是带有用户数组的JSON。我想使用Symfony2序列化程序配置JSON中的字段。我希望返回" X-Total-Count"中的用户总数量。报头中。

据我所知,最好使用FOSRestBundle。所以,我试过这个:

<?php

namespace AppBundle\Controller;

use FOS\RestBundle\Controller\FOSRestController;
use Symfony\Component\HttpFoundation\Request;
use FOS\RestBundle\Controller\Annotations;
use FOS\RestBundle\Request\ParamFetcherInterface;

class UserController extends FOSRestController
{
    /**
     * List all notes.
     *
     * @Annotations\QueryParam(name="_page", requirements="\d+", default=1, nullable=true, description="Page number.")
     * @Annotations\QueryParam(name="_perPage", requirements="\d+", default=30, nullable=true, description="Limit.")
     * @Annotations\QueryParam(name="_sortField", nullable=true, description="Sort field.")
     * @Annotations\QueryParam(name="_sortDir", nullable=true, description="Sort direction.")
     *
     * @Annotations\View()
     *
     * @param Request               $request      the request object
     * @param ParamFetcherInterface $paramFetcher param fetcher service
     *
     * @return array
     */
    public function getUsersAction(Request $request, ParamFetcherInterface $paramFetcher)
    {
        $sortField = $paramFetcher->get('_sortField');
        $sortDir = $paramFetcher->get('_sortDir');
        $page = $paramFetcher->get('_page');
        $limit = $paramFetcher->get('_perPage');

        $orderBy = null;
        if ($sortField && $sortDir) {
            $orderBy = [
                $sortField => $sortDir
            ];
        }
        $offset = ($page - 1) * $limit;

        $repository = $this->getDoctrine()
            ->getRepository('AppBundle:User');
        $users = $repository->findBy([], $orderBy, $limit, $offset);

        return $users;
    }
    ...
}

我认为这段代码很好,因为它很短,我可以使用序列化程序。我可以配置哪些字段应该响应。但在这个例子中,我没有响应对象,我无法设置&#34; X-Total-Count&#34;头。此外,我不知道如何获得总行数。

我尝试了另一个案例:

<?php

namespace AppBundle\Controller;

use Symfony\Component\HttpFoundation\JsonResponse;
use FOS\RestBundle\Controller\FOSRestController;
use Symfony\Component\HttpFoundation\Request;
use FOS\RestBundle\Controller\Annotations;
use FOS\RestBundle\Request\ParamFetcherInterface;
use Doctrine\ORM\Tools\Pagination\Paginator;

class UserController extends FOSRestController
{
    /**
     * List all users.
     *
     * @Annotations\QueryParam(name="_page", requirements="\d+", default=1, nullable=true, description="Page number.")
     * @Annotations\QueryParam(name="_perPage", requirements="\d+", default=30, nullable=true, description="Limit.")
     * @Annotations\QueryParam(name="_sortField", nullable=true, description="Sort field.")
     * @Annotations\QueryParam(name="_sortDir", nullable=true, description="Sort direction.")
     *
     * @param Request               $request      the request object
     * @param ParamFetcherInterface $paramFetcher param fetcher service
     *
     * @return array
     */
    public function getUsersAction(Request $request, ParamFetcherInterface $paramFetcher)
    {
        $sortField = $paramFetcher->get('_sortField');
        $sortDir = $paramFetcher->get('_sortDir');
        $page = $paramFetcher->get('_page');
        $limit = $paramFetcher->get('_perPage');
        $offset = ($page - 1) * $limit;

        $em = $this->getDoctrine()->getEntityManager();
        $qb = $em->createQueryBuilder();

        $qb->select('u')
            ->from('AppBundle:User', 'u');

        if ($sortField && $sortDir) {
            $qb->orderBy('u.' . $sortField, $sortDir);
        }

        $query = $qb->getQuery();

        $query->setFirstResult($offset)
            ->setMaxResults($limit);

        $paginator = new Paginator($query);
        $totalCount = $paginator->count();

        $users = $query->getResult();

        $response = new JsonResponse($users);
        $response->headers->set('X-Total-Count', $totalCount);
        return $response;
    }
    ...
}

在这种情况下,我有一个响应对象,我可以设置一个&#34; X-Total-Count&#34;头。我可以使用Paginator获得总行数。但我不能像前面的例子那样使用序列化器。我认为这段代码太多而且不优雅。我使用查询构建器,查询,paginator来获取用户列表。

请告诉我如何使用简单优雅的代码获取用户列表。

1 个答案:

答案 0 :(得分:1)

不是像第一个代码示例中那样返回$ users,而是可以这样做:

$view = $this
    ->view($users, 200);
    ->setHeader('X-Total-Count', $totalCount);
return $this->handleView($view);

此外,您可以创建扩展基础存储库的存储库,并在那里移动您的分页逻辑。那样你的控制器会非常薄。