如何在Symfony 2存储库中处理条件查询操作?

时间:2014-01-11 02:25:33

标签: php symfony doctrine dry

我的应用程序需要有条件地操作查询。详细说明;如果当前登录的用户是管理员,则需要限制查询的结果集。

我真的不喜欢我现在正在重复多少,我已经知道这样做很糟糕,但是这里有:

我的一个控制器的一个例子:

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这个存储库中发生了什么。以下是来自所述存储库的2个方法:

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();
}

所以,我的问题是,我应该怎么做这个干?我知道我不应该注入用户,安全上下文或任何类似的东西,因为这个存储库应该只关注自己。但是我很难想到处理查询操作的最佳方法(我不反对使用QueryBuilder,如果需要这样做可以使这个结构更好一些)。

1 个答案:

答案 0 :(得分:1)

您可以添加第二个参数,并在QueryBuilder方法中使用findById

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-way将是一个单一的函数,它使用某种$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();
}