0

Symfony : pagination à partir de plusieurs requêtes doctrine

2011-08-10 dans Petits coups de pouce, Réalisations par vibby

Dans la continuité, voici comment gérer la pagination à partir de plusieurs requêtes DQL :

A créer dans un fichier sfMultiDoctrinePager.class.php, et à placer qque part dans votre lib

 
<?php
 
/**
 * dualTableDoctrinePager
 * a pager for combining the results of multiple tables
 *
 * @author vibby
 */
class sfMultiDoctrinePager extends sfDoctrinePager
{
  protected $queries = null;
 
  public function setQueries($queries)
  {
    $pagerQueries = array();
    foreach($queries as $key => $query)
    {
      $pagerQueries[$key]['query']  = $query;
      $pagerQueries[$key]['active'] = true;
    }
 
    $this->queries = $pagerQueries;
  }
 
  public function getCountQueries()
  {
    $queries = array();
 
    foreach($this->queries as $key => $query)
    {
      $queries[$key]['query'] = clone $query['query'];
      $queries[$key]['query']
        ->offset(0)
        ->limit(0);
    }
 
    return $queries;
  }
 
  public function init()
  {
    $this->results = null;
 
    $countQueries = $this->getCountQueries();
    $count = 0;
    $counts = array();
 
    // remebering counts for each table
    foreach($countQueries as $countQuery)
    {
      $currentCount = $countQuery['query']->count();
      $counts[] = $currentCount;
      $count += $currentCount;
    }
 
    $this->setNbResults($count);
 
    // reseting queries
    foreach($this->queries as &$query)
    {
      $query['query']
        ->offset(0)
        ->limit(0)
      ;
    }
 
    if (0 == $this->getPage() || 0 == $this->getMaxPerPage() || 0 == $this->getNbResults())
    {
      $this->setLastPage(0);
    }
    else
    {
      $offset = ($this->getPage() - 1) * $this->getMaxPerPage();
 
      $this->setLastPage(ceil($this->getNbResults() / $this->getMaxPerPage()));
 
      	//For every query
      	$iQuery = -1;
      	$totalCount = 0;
        foreach($this->queries as $key => &$query)
        {
        	$iQuery ++;
        	//Is this query a part of the wanted ?
        	echo $counts[$iQuery].' + '.$totalCount.' <= '.$offset.'<br />';
        	echo $totalCount.' > '.$offset.' + '.$this->getMaxPerPage().'<br />';
        	if (
        		($counts[$iQuery] + $totalCount <= $offset)
        	||
        		($totalCount >= ($offset + $this->getMaxPerPage()))
        	)
        	{
        		$query['active'] = false;
        	} else {
        		echo ($offset - $totalCount + 1).' et limite : '.($offset + $this->getMaxPerPage() - $totalCount);
        		$query['active'] = true;
            $query['query']
              ->offset(max(0,$offset - $totalCount))
              ->limit($offset + $this->getMaxPerPage() - $totalCount);
        	}
        	$totalCount += $counts[$iQuery];
        }
 
    }
  }
 
  public function getResults($hydrationMode = null)
  {
    $results = array();
 
    foreach($this->queries as $key => $query)
    {
      if($query['active'])
      {
        $results[] = $query['query']->execute(array(), $hydrationMode);
      }
      else
      {
        $results[] = array();
      }
    }
 
    return $results;
  }
}

Et cela s’appelle comme cela depuis le controller :

	$queries[] = Doctrine::getTable('myTable')->anyQueryCreation();
	$queries[] = Doctrine::getTable('myOtherTable')->anyQueryCreation();
	$queries[] = Doctrine::getTable('myYetAnotherTable')->anyQueryCreation();
 
  	$this->pager= new sfMultiDoctrinePager(
	    'consuleadsAccount',
	    sfConfig::get('app_directory_count_default')
	  );
	  $this->pager->setQueries($queries);
         // $this->pager->setQueries($queries2);
 
 
 
	  $this->pager->setPage($request->getParameter('page',1));
	 // $this->pager->setQueries($queries2);
 
    $this->pager->init();

Enjoy :)

Envoyer mon retour






+ 5 = 10