5
\$\begingroup\$

I have a Symfony2 project. I have an Entity Asset which can have relations with Category. I store a categoryCount-field within the Asset to determine if an asset has one, to select those fast via a DQL-query depending on the current user state.

Now found myself writing something along the lines of this in my AssetRepository:

/**
 * @param string $orderBy
 * @param int $mode
 *
 * @return \Doctrine\ORM\Query
 */
public function getQueryForAll($orderBy = 'DESC', $mode = self::FILTER_WITHOUT_QUARANTINED)
{
    $qb = $this->createQueryBuilder('asset');
    $qb->orderBy('asset.updatedAt', $orderBy);

    $filter = $this->getQuarantinedCriteria($mode);

    if ($filter) {
        $qb->addCriteria($filter);
    }

    return $query = $qb->getQuery();
}

/**
 * @param int $mode
 *
 * @return Criteria|null
 */

protected function getQuarantinedCriteria($mode = self::FILTER_WITHOUT_QUARANTINED) {
    $filter = null;

    if ($mode === self::FILTER_WITHOUT_QUARANTINED) {
        $filter = Criteria::create()
            ->andWhere(Criteria::expr()->gt('categoryCount', 0));
    } else if ($mode === self::FILTER_ONLY_QURANTINED) {
        $filter = Criteria::create()
            ->andWhere(Criteria::expr()->eq('categoryCount', 0));
    }

    return $filter;
}

This doesn't feel right to me. The $mode flag triggers my code smell alarm, I also am worrying about passing it into each asset querying method.

Furthermore, since I will have to set the mode depending on the state of the current logged in user, I also am worried that I will produce code duplications by doing a lot of if-user-has-the-rights-checks in my actions or services:

/**
 * @Route("/all_assets/{page}",
 *         name="get_paginated_assets",
 *         requirements={"page" = "\d+"},
 *         defaults={"page" = "1"},
 *         options={"expose"=true}
 * )
 */

public function getPaginatedAssetActions($page)
{
    $repo = $this->getAssetRepository();

    $isAllowedToViewRestrictedAssets =  $this->getCurrentUser()->isAdmin();

    if ($isAllowedToViewRestrictedAssets) {
        $mode = Entity\AssetRepository::FILTER_SHOW_ALL;
    }

    $query = $repo->getQueryForAll($mode);

    $pagerfanta = new Pagerfanta(new DoctrineORMAdapter($query));
    $data = $this->getCurrentPagedResults($pagerfanta, $page);

    $view = $this->view();
    $view->setFormat('json');
    $view->setData($data);

    return $view;
}

Is this the right way to implement the logic to enable filters in a Repository? Feedback on whether there is a more decoupled way would be highly appreciated.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

You can try to use SQLFilter for this purpose. It allows you to tune SQL query based on some logic. You can pass information about your user's state into filter through DI container and use this information to tune your SQL query. Please note that unlike repositories - SQLFilter works on SQL level, not on DQL. More information can be found into Doctrine's documentation.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.