2013-05-18 9 views
5

Mam następujący schemat bazy danych:Symfony2 Doktryna dostać losowy produkt z kategorii

table 'products' 
id 
category_id 

i oczywiście tabeli kategorii, tylko z identyfikatorem.

Dane wyglądać tak:

Products 
-------------------- 
| id | category_id | 
-------------------- 
| 0 | 1   | 
| 1 | 1   | 
| 2 | 1   | 
| 3 | 2   | 
| 4 | 2   | 
| 5 | 1   | 
-------------------- 

chciałbym wybrać kategorię (na przykład kategoria 1), więc zaznaczyć wszystkie wiersze z tej kategorii w mojej klasie produktowej repozytorium:

return $this 
    ->createQueryBuilder('u') 
    ->andWhere('u.category = :category') 
    ->setMaxResults(1) 
    ->setParameter('category', $category->getId()) 
    ->getQuery() 
    ->getSingleResult() 
; 

Jak mogę teraz wybrać losowy produkt? Ponadto: Czy można to rozwiązać poprzez relacje?

Mam OneToMany relacji pomiędzy podmiotami „Kategoria” i „Produkt”, więc mogę również dostać wszystkie produkty poprzez category-> getProducts() ...

Każda pomoc będzie bardzo przydatna, dzięki

Odpowiedz

12

Najpierw należy policzyć całkowitą liczbę produktów, a następnie wygenerować losowe przesunięcie, aby wybrać losowy produkt.

To powinno Ci zacząć:

$count = $this->createQueryBuilder('u') 
      ->select('COUNT(u)') 
      ->getQuery() 
      ->getSingleScalarResult(); 

A potem można wygenerować liczbę losową między telefonem a całkowitą liczbą wierszy 1.

return $this->createQueryBuilder('u') 
    ->where('u.category = :category') 
    ->setFirstResult(rand(0, $count - 1)) 
    ->setMaxResults(1) 
    ->setParameter('category', $category->getId()) 
    ->getQuery() 
    ->getSingleResult() 
; 

co przekłada się na:

SELECT * FROM products WHERE category_id = ? LIMIT 1, {random offset} 
+0

Gdyby 'getResult' na zapytania count nie być' getSingleScalarResult'? – Machiel

+0

Wiem, że ten fragment działał, gdy odpowiedziałam, ale od pewnego czasu nie tknąłem Doktryny, więc rzeczy mogły się zmienić. –

+1

Oto funkcja gotowa do użycia: https://gist.github.com/Thinkscape/124d658e4076421c0516 –

0

użyć tej funkcji pomocnika:

<?php 
use Doctrine\ORM\EntityManager; 

/** 
* Retrieve one random item of given class from ORM repository. 
* 
* @param EntityManager $em The Entity Manager instance to use 
* @param string  $class The class name to retrieve items from 
* @return object 
*/ 
function getRandomDoctrineItem(EntityManager $em, $class) 
{ 
    static $counters = []; 
    if (!isset($counters[$class])) { 
     $this->counters[$class] = (int) $this->manager->createQuery(
      'SELECT COUNT(c) FROM '. $class .' c' 
     )->getSingleScalarResult(); 
    } 
    return $em 
     ->createQuery('SELECT c FROM ' . $class .' c ORDER BY c.id ASC') 
     ->setMaxResults(1) 
     ->setFirstResult(mt_rand(0, $counters[$class] - 1)) 
     ->getSingleResult() 
    ; 
} 

Przykład użycia:

$randomItem = getRandomDoctrineItem($em, 'Application\Entity\Post'); 
Powiązane problemy