return random data form database in random order and with limit

Viewed 116

I'm new with symfony and I'm trying to view data from one of my tables with random order and a limit of 4. I tried doing it in the repository but RAND() is not working so I'm trying in the controller.

The error is the following one:

"Warning: array_rand() expects parameter 1 to be array, object given"

And I don't understand why, when in the $response I set the data into an array.

This is my actual code:

/**
* @Route("/ws/random/superviviente", name="ws_random_survi")
*/
    public function randomSurvi(Request $request): Response
    {
        $data = $request->request->all();
        $entityManager = $this->getDoctrine()->getManager();

        $randomPerks = $entityManager->getRepository(Perks::class)
            ->getRandomPerks();
        
        $response = new JsonResponse();
        $response -> setStatusCode(200);
        $response -> setData(array('random perk' => $randomPerks));

        $resultRandom = array_rand($response);

        return $resultRandom;
        
    }
2 Answers

You are trying to use array_rand on a doctrine array collection.

You could either convert it as array and back to a doctrine array :

use Doctrine\Common\Collections\ArrayCollection;
public function randomSurvi(Request $request): Response
    {
        $data = $request->request->all();
        $entityManager = $this->getDoctrine()->getManager();

        $randomPerks = $entityManager->getRepository(Perks::class)
            ->getRandomPerks();
        
        $resultRandom = new ArrayCollection(array_rand($randomPerks->toArray()));

        return new JsonResponse($resultRandom);
        
    }

Otherwise it would work with shuffle :

 $randomPerks = $entityManager->getRepository(Perks::class)->getRandomPerks();
 $randomPerks = shuffle($randomPerks);

Or get random perks directly through your method in your repository.

See example from @Krzysztof Trzos:

  public function getRandomProducts($amount = 7)
    {
        return $this->getRandomProductsNativeQuery($amount)->getResult();
    }


/**
 * @param int $amount
 * @return ORM\NativeQuery
 */
public function getRandomProductsNativeQuery($amount = 7)
{
    # set entity name
    $table = $this->getClassMetadata()
        ->getTableName();

    # create rsm object
    $rsm = new ORM\Query\ResultSetMapping();
    $rsm->addEntityResult($this->getEntityName(), 'p');
    $rsm->addFieldResult('p', 'id', 'id');

    # make query
    return $this->getEntityManager()->createNativeQuery("
        SELECT p.id FROM {$table} p ORDER BY RAND() LIMIT 0, {$amount}
    ", $rsm);
}

You could write your own query to achieve this, so create a new method inside the repository like so:

public function getRandomPerks(int $limit): array
{
    $queryBuilder = $this->createQueryBuilder('p');

    return $queryBuilder
        ->setMaxResults($limit)
        ->orderBy('RAND()')
        ->getQuery()
        ->getResult();
}

Then in your controller all you would to do is call the method and pass a limit:

$randomPerks = $entityManager->getRepository(Perks::class)
    ->getRandomPerks(4);
Related