Foros del Web » Programando para Internet » PHP » Symfony »

LeftJoin + setMaxResults

Estas en el tema de LeftJoin + setMaxResults en el foro de Symfony en Foros del Web. Hola, Estoy intentando limitar los resultados de una consulta con setMaxResults. La consulta tiene un LeftJoin de dos tablas Código: $qb = $this->createQueryBuilder('b') ->select('b, c') ...
  #1 (permalink)  
Antiguo 15/10/2011, 16:37
Avatar de punk567  
Fecha de Ingreso: septiembre-2006
Ubicación: Montevideo
Mensajes: 265
Antigüedad: 17 años, 6 meses
Puntos: 5
LeftJoin + setMaxResults

Hola,

Estoy intentando limitar los resultados de una consulta con setMaxResults. La consulta tiene un LeftJoin de dos tablas

Código:
$qb = $this->createQueryBuilder('b')
           ->select('b, c')
           ->leftJoin('b.comments', 'c')
           ->groupBy('b')
           ->addOrderBy('b.created', 'DESC');

        if (false === is_null($limit))
            $qb->setMaxResults($limit);

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

El problema es que el límite funciona bien, pero los comentarios asociados siempre devuelven 1, en el template: {{ blog.comments|length }}

He leído en la documentación de Doctrine que setMaxResults() no funciona correctamente en consultas con "fetch-join"

Cita:
If your query contains a fetch-joined collection specifying the result limit methods are not working as you would expect. Set Max Results restricts the number of database result rows, however in the case of fetch-joined collections one root entity might appear in many rows, effectively hydrating less than the specified number of results.
Alguna idea de como establecer el máximo de resultados?
  #2 (permalink)  
Antiguo 15/10/2011, 17:55
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 3 meses
Puntos: 845
Respuesta: LeftJoin + setMaxResults

Podrias utilizar el Paginator de DoctrineExtensions.

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)
  #3 (permalink)  
Antiguo 15/10/2011, 18:04
Avatar de punk567  
Fecha de Ingreso: septiembre-2006
Ubicación: Montevideo
Mensajes: 265
Antigüedad: 17 años, 6 meses
Puntos: 5
Respuesta: LeftJoin + setMaxResults

HOla masterpuppet

Lo he utilizado y obtuve el mismo resultado

Gracias, saludos
  #4 (permalink)  
Antiguo 15/10/2011, 18:14
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 3 meses
Puntos: 845
Respuesta: LeftJoin + setMaxResults

Que tal punk567,

Postea el código tal cual lo has probado.

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)
  #5 (permalink)  
Antiguo 15/10/2011, 19:27
Avatar de punk567  
Fecha de Ingreso: septiembre-2006
Ubicación: Montevideo
Mensajes: 265
Antigüedad: 17 años, 6 meses
Puntos: 5
Respuesta: LeftJoin + setMaxResults

Hola

Parece que ahora con DoctrineExtensions funciona bien, el tema está en "GROUP BY" (me parece, soy novato)

con este código que se encuentra en Repository/BlogRepository.php

Código:
$qb = $this->createQueryBuilder('b')
           ->select('b, c')
           ->leftJoin('b.comments', 'c')
           ->groupBy('b')
           ->addOrderBy('b.created', 'DESC');

           if (false === is_null($limit))
                $qb->setMaxResults($limit);
quitando el "groupBy" no funciona bien el límite, en lugar de 4 resultados (ej.) devolvía 3, y asi con otros números para $limit.
supongo que es por el leftJoin.

con "groupBy('b')" funciona el límite, pero como decía antes la cantidad de blog.comments si era mayor que 0, siempre quedaba en 1.


Con la nueva extensión no puedo usar el código en BlogRepository.php, o no se como hacerlo.
Anteriormente tenía un problema con $this->createQueryBuilder('b'), parece la función de paginate esperaba un objecto Query en lugar de QueryBuilder

entonces lo implementé en el controller directamente
así


Código:
    public function indexAction()
    {
        $em = $this->getDoctrine()
                   ->getEntityManager();


        $qb = $em->createQuery('SELECT b, c FROM BloggerBlogBundle:Blog b LEFT JOIN b.comments c');

        
            $count = Paginate::getTotalQueryResults($qb); // Step 1
            $paginateQuery = Paginate::getPaginateQuery($qb, 0, 3); // Step 2 and 3
        
        
        $latestBlogs = $paginateQuery->getResult();
        

        return $this->render('BloggerBlogBundle:Page:index.html.twig', array(
            'blogs' => $latestBlogs
        ));
    }
y funciona bien, antes no había funcionado porque había agregado "GROUP BY b" en la consulta


Una pregunta: es posible obtener la query en BlogRepository , como lo estaba haciendo antes?

gracias de nuevo, y disculpas si esto es confuso
  #6 (permalink)  
Antiguo 15/10/2011, 20:25
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 3 meses
Puntos: 845
Respuesta: LeftJoin + setMaxResults

Claro que puedes, no es mas que pasar el código que tienes en el controller al repository y luego llamar al repository para obtener la query, aunque me parece mejor devolver directamente los resultados.

Algo asi:

Controller
Código PHP:
Ver original
  1. public function indexAction()
  2. {
  3.     $lastestBlogs = $this->getDoctrine()
  4.                          ->getEntityManager()
  5.                          ->getRepository('BlogRepository')
  6.                          ->getLatestBlogs($this->get('request')->query->get('page', 1));
  7.  
  8.     return $this->render('BloggerBlogBundle:Page:index.html.twig', array(
  9.             'blogs' => $latestBlogs
  10.         ));
  11. }

Repository
Código PHP:
Ver original
  1. public function getLatestBlogs($page = 1, $limitPerPage = 10)
  2. {
  3.     $dql = $em->createQuery('SELECT b, c FROM BloggerBlogBundle:Blog b LEFT JOIN b.comments c');
  4.     ...
  5.     $count = Paginate::getTotalQueryResults($dql); // Step 1
  6.     $paginateQuery = Paginate::getPaginateQuery($qb, $offest, $limitPerPage);
  7.  
  8.     return $paginateQuery->getResult();
  9. }

Te dejo una referencia a un bundle que te puede interesar http://0hlsson.se/2011/09/13/paginat...ginatorbundle/

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)
  #7 (permalink)  
Antiguo 15/10/2011, 21:15
Avatar de punk567  
Fecha de Ingreso: septiembre-2006
Ubicación: Montevideo
Mensajes: 265
Antigüedad: 17 años, 6 meses
Puntos: 5
Respuesta: LeftJoin + setMaxResults

hola de nuevo

copié el código como lo has puesto, pero da este error

Fatal error: Call to a member function createQuery() on a non-object in ...BlogRepository.php on line 40

esta es la línea 40

$dql = $em->createQuery('SELECT b, c FROM BloggerBlogBundle:Blog b LEFT JOIN b.comments c');

probé con $this->createQuery('.......

y me da este error

Undefined method 'createQuery'. The method name must start with either findBy or findOneBy!


gracias por el enlace, parece interesante, voy a ver si puedo aplicarlo
  #8 (permalink)  
Antiguo 16/10/2011, 04:44
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 3 meses
Puntos: 845
Respuesta: LeftJoin + setMaxResults

Es que no era para copiar y pegar, era para que te hagas una idea de como hacerlo, para obtener el EntityManager en el repositorio utiliza getEntityManager,

Código PHP:
Ver original
  1. $dql = $this->getEntityManager()->createQuery(...);
  2. ...
  3. $count = Paginate::getTotalQueryResults($dql);
  4. $paginateQuery = Paginate::getPaginateQuery($dql, $offset, $limitPerPage);
  5. ...
__________________
http://es.phptherightway.com/
thats us riders :)
  #9 (permalink)  
Antiguo 16/10/2011, 18:21
Avatar de punk567  
Fecha de Ingreso: septiembre-2006
Ubicación: Montevideo
Mensajes: 265
Antigüedad: 17 años, 6 meses
Puntos: 5
Respuesta: LeftJoin + setMaxResults

Ahhhh , entiendo

Y el parámetro $page es para ir mostrando las páginas en caso de que haya más de una?

esto tendría que setearlo en routing.yml y en algún lado más?
  #10 (permalink)  
Antiguo 17/10/2011, 15:21
Avatar de punk567  
Fecha de Ingreso: septiembre-2006
Ubicación: Montevideo
Mensajes: 265
Antigüedad: 17 años, 6 meses
Puntos: 5
Respuesta: LeftJoin + setMaxResults

Buenas, lo he resuelto de la siguiente manera, a lo mejor a alguien le puede servir, aunque seguramente haya una manera más eficaz.

Controller
Código:
    public function indexAction($page)
    {
        $latestBlogs = $this->getDoctrine()
                             ->getEntityManager()
                             ->getRepository('BloggerBlogBundle:Blog')
                             ->getLatestBlogs($page, 5 );

        return $this->render('BloggerBlogBundle:Page:index.html.twig', array(
                'blogs' => $latestBlogs
            ));
    }
Repository
Código:
    public function getLatestBlogs($page = 1, $limitPerPage = 5)
    {
        $dql = $this->getEntityManager()->createQuery('SELECT b, c FROM BloggerBlogBundle:Blog b LEFT JOIN b.comments c');
        //...
        $count = Paginate::getTotalQueryResults($dql); // Step 1
        
        if ( $page == 1 ) {
            $offset = 0;
        }
        if ( $page == 2 ) {
            $offset = 5;
        }        
              
        $paginateQuery = Paginate::getPaginateQuery($dql, $offset, $limitPerPage);
     
        return $paginateQuery->getResult();
    }
Routing
Código:
BloggerBlogBundle_homepage:
    pattern:  /{page}
    defaults: { _controller: BloggerBlogBundle:Page:index, page:1 }
    requirements:
        _method:  GET
Template
Código:
    <div>
        <a href="{{ path('BloggerBlogBundle_homepage', { 'page': 1 }) }}">1</a> || <a href="{{ path('BloggerBlogBundle_homepage', { 'page': 2 }) }}">2</a>
    </div>
He puesto el número de páginas a mano (1 y 2, con 5 resultados por página) supongo que con el total de resultados de la consulta, divido por el número de resultados por página a mostrar, se puede obtener la paginación de manera genérica

Saludos y gracias de nuevo masterpuppet
  #11 (permalink)  
Antiguo 24/05/2014, 15:32
 
Fecha de Ingreso: mayo-2014
Mensajes: 1
Antigüedad: 9 años, 11 meses
Puntos: 0
Respuesta: LeftJoin + setMaxResults

/*
* PAGINADOR DE RESULTADOS DE CONSULTAS
*/
public function paginador($array, $firstResult=0, $maxResults=10)
{
$matrix =array();
$ultimo = count($array); // Ultima posición del array
$hasta = $firstResult + $maxResults;
$hasta = ($hasta > $ultimo)? $ultimo : $hasta;

if ($firstResult <= $ultimo)
for ($i = $firstResult; $i < $hasta; $i++) array_push($matrix, $array[$i]);
return $matrix;
}

Etiquetas: Ninguno
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 13:34.