Home > Back-end >  Doctrine Querybuilder doesnt return exact matches
Doctrine Querybuilder doesnt return exact matches

Time:10-11

I have and api endpoint which should return a user based on his id : user/{id}.

In my controller i have the following code:

/**
 * @Api\Get("user/{id}")
 * @SWG\Parameter(name="id", type="string", in="path", required=true)
 */
public function getUser(Request $request, string $id) {
    $user = $this->getDoctrine()->getManager()->getRepository('App\Entity\User')->findUser($id);
    return $this->view($user);
}

In my repository i have the following code:

public function findUser(string $id) {
    $qb = $this->createQueryBuilder('a');
    $qb->andWhere($qb->expr()->eq('a.id',':id'))->setParameter('id',$id);

    return $qb->getQuery()->getOneOrNullResult();
}

it is working fine when getting user/4, but it is also working when getting user/4ruqbu.

I just want to get the user on user/4 and no result on user/4ruqbu. It should return the exact match. I think the problem is that the id parameter is a string. if i change it to int it is working, but i get an error instead of no result if i try user/4eiugq.

Is there a way to handle that?

CodePudding user response:

Your route accepts any string for your id parameter which means that any value will make its way to your repository method. Then if you try to use a string which starts with a numeric value as an integer, you will get that integer. Try for yourself on 3v4l.org:

var_dump((int)'4ruqbu');    // output: int(4)

You could make use of parameters validation using a Regex:

/**
 * @Api\Get("user/{id<\d >}")
 */
public function getUser(Request $request, int $id) {
    // ...
}

This should now fail for URIs such as /user/4ruqbu as it does not meet the route requirements.


Some improvements:

If you installed sensio/framework-extra-bundle you can benefit of the ParamConverter and replace string $id with a user:

public function getUser(User $user, Request $request)
{
    // ...
}

Avoid fetching services related to Doctrine with $this->getDoctrine() etc. Use autowiring instead. If you need the Entity Manager to save/update/remove entities, add a Doctrine\ORM\EntityManagerInterface argument to your controller method. If you need to query for entities using a repository, add an argument typed with its class like App\Repository\UserRepository in your case:

// Example of controller method fetching services by autowiring:
public function myAction(EntityManagerInterface $em, UserRepository $userRepo)
{
    // ...
}
  • Related