2014-01-11 18 views
1

我的應用程序需要有條件地操作查詢。詳細說明;如果當前登錄的用戶是而不是管理員,則需要限制查詢的結果集。如何處理Symfony 2存儲庫中的條件查詢操作?

我真的不喜歡多少我正在重複自己,我已經知道這是做的好方法,但在這裏有雲:

從我的控制器的一個例子:

try { 
    if ($sc->isGranted('ROLE_ADMIN')) { 
     $gallery = $gr->findById($id); // If the user is an admin, show all 
    } else { 
     $gallery = $gr->findActiveById($id); // Otherwise, show only active ones 
    } 
} catch (NoResultException $e) { 
    throw $this->createNotFoundException('That gallery doesn\'t exist!'); 
} 

你可能已經猜到了$gr這個庫是怎麼回事。這裏是從上述存儲庫中提出的兩種方法:

public function findById($id) 
{ 
    $dql = ' 
     SELECT 
      g, 
      gci, 
      gi, 
      t, 
      gv 
     FROM 
      DWIPortfolioBundle:Gallery AS g 
     LEFT JOIN 
      g.coverImage AS gci 
     LEFT JOIN 
      g.images AS gi 
     LEFT JOIN 
      g.tags AS t 
     LEFT JOIN 
      g.views AS gv 
     WHERE 
      g.id = :id'; 

    $query = $this->getEntityManager()->createQuery($dql) 
     ->setParameter('id', $id); 

    return $query->useResultCache(true) 
     ->getSingleResult(); 
} 

public function findActiveById($id) 
{ 
    $dql = ' 
     SELECT 
      g, 
      gci, 
      gi, 
      t, 
      gv 
     FROM 
      DWIPortfolioBundle:Gallery AS g 
     LEFT JOIN 
      g.coverImage AS gci 
     LEFT JOIN 
      g.images AS gi 
     LEFT JOIN 
      g.tags AS t 
     LEFT JOIN 
      g.views AS gv 
     WHERE 
      g.id = :id 
     AND 
      g.isActive = 1'; 
    // ^^^^^^^^^^^^^^^^^^^^ 
    // This last 'AND' bit is the only part that is 
    // different from the method above this 

    $query = $this->getEntityManager()->createQuery($dql) 
     ->setParameter('id', $id); 

    return $query->useResultCache(true) 
     ->getSingleResult(); 
} 

所以,我的問題是,我該如何去做這個DRY?我知道我不應該注入用戶,安全上下文或任何類型的東西,因爲這個存儲庫應該只關注自身。但我努力想辦法處理查詢的最佳方式(如果需要使用QueryBuilder來使這種結構更好一些,我並不反對)。

回答

1

您可以添加第二個參數並在findById方法中使用QueryBuilder

public function findById($id, $is_active=false) { 
    $qb = $this->getEntityManager()->createQueryBuilder(); 
    $query = $qb->select("g, gci, gi, t, gv") 
      ->from("DWIPortfolioBundle:Gallery", "g") 
      ->leftJoin('g.coverImage', 'gi') 
      // .... 
      ->where('g.id = :id') 
      ->setParameter('id', $id); 
    if ($is_active) { 
     $query->andWhere('g.isActive = 1'); 
    } 

    return $query->getQuery()->useResultCache(true)->getSingleResult(); 

} 

我想更多的DRY-的辦法是有它檢索顯示畫廊的多種可能的方式單一的功能,使用某種$options數組:

public function getGallery($options) { 
    $qb = $this->getEntityManager()->createQueryBuilder(); 
    $query = $qb->select("g") 
     ->from("DWIPortfolioBundle:Gallery", "g"); 

    if ($options) { 
     if (isset($options['id'])) { 
      $query->andWhere('g.id = :id')->setParameter('id', $options['id']); 
     } 

     if (isset($options['is_active'])) { 
      $query->andWhere('g.isActive = :is_active')->setParameter('is_active', $options['is_active']); 
     } 

     if (isset($options['limit'])) { 
      $query->setMaxResults($options['limit']); 
     } 

     // Any other filtering options you might need 
    } 

    return $query->getQuery()->useResultCache(true)->getResult(); 
} 
+0

我喜歡第二種方法,因爲我」我之前做過類似的事情,並且在某些方面可以更清楚地看到發生了什麼。儘管對於這個特殊的問題,我可能會選擇第一種方式,因爲手頭的任務相當簡單。我將來可能會使用第二種方法。 – Seer

+1

QueryBuilder是一個很棒的工具。它有可能用它構建一些非常複雜和靈活的過濾/分頁/排序功能。 – reafle

+1

另外,你需要那麼多的連接嗎?您可以使用默認存儲庫'findBy'方法,' - > findBy(array(id => $ id,'isActive'=> true))',如[here]所示(http://docs.doctrine-project.org /en/2.0.x/reference/working-with-objects.html#by-simple-conditions) – reafle

相關問題