blahblah blahblah - 3 months ago 41
PHP Question

Symfony REST API: query with multiple parameters

How can I implement method that would return list of services depending on parameters provided in URL?

So if there are no parameters, all services are returned. If user and category provided, then filter by both params. If only user or only category provided, filter by one of the params.

/**
* @Route("/", name="api_services_search")
* @Method("GET")
* @ApiDoc(
* section = "Service",
* description="Search services",
* parameters={
* {"name"="category", "dataType"="int", "required"=true, "description"="Category ID"}
* {"name"="user", "dataType"="int", "required"=true, "description"="User ID"}
* },
* output="CoreBundle\Entity\Service"
* )
*/
public function searchAction(Request $request){

$categoryId = $request->query->get('category');
$userId = $request->query->get('user');

$result = new JsonResponse();

if($categoryId){
$category = $this->getDoctrine()->getRepository('CoreBundle:ServiceCategory')->find($categoryId);
if($category == null){
throw new ApiException('category not found');
}
$serviceList = $this->getDoctrine()
->getRepository('CoreBundle:Service')->findBy(array('serviceCategory' => $category));
}
else if($userId){
$user = $this->getDoctrine()->getRepository('CoreBundle:BasicUser')->find($userId);
if($user == null){
throw new ApiException('user not found');
}

$serviceList = $this->getDoctrine()
->getRepository('CoreBundle:Service')->findBy(array('basicUser' => $user));
} else{
$serviceList = $this->getDoctrine()
->getRepository('CoreBundle:Service')->findAll();
}

$serviceListJson = $this->serializeDataObjectToJson($serviceList);

$result->setContent($serviceListJson);
return $result;
}


Example URL:

http://127.0.0.1:8000/api/v1/services/?category=3&user=4


I have error:

Too many parameters: the query defines 1 parameters and you bound 2 (500 Internal Server Error)


Also I am looking for maintaible solution where I can easily add more parameters to URL in the future

VaN VaN
Answer

I would go with something like this. I'm afraid you can't make it more generic and agnostic from query parameters adds/edits.

/**
 * Controller action
 */
public function searchAction(Request $request)
{
    $em = $this->getDoctrine()->getManager();


    $serviceList = $em->getRepository('CoreBundle:Service')->fetchFromFilters([
        'serviceCategory' => $request->query->get('category', null);,
        'basicUser' => $request->query->get('user', null),
    ]);

    $serviceListJson = $this->serializeDataObjectToJson($serviceList);

    $result = new JsonResponse();
    $result->setContent($serviceListJson);
    return $result;
}

/**
 * Repository fetching method
 */
public function fetchFromFilter(array $filters)
{
    $qb = $this->createQueryBuilder('s');

    if (null !== $filters['serviceCategory']) {
        $qb
            ->andWhere('s.serciceCategory = :serviceCategory')
            ->setParameter('serviceCategory', $filters['serviceCategory'])
        ;
    }
    if (null !== $filters['basicUser']) {
        $qb
            ->andWhere('s.basicUser = :basicUser')
            ->setParameter('basicUser', $filters['basicUser'])
        ;
    }

    return $qb->getQuery()->getResult();
}
Comments