Skip to content

Repository Query

A Repository query is an abstraction of the doctrine repository.

Requirement

Entities must implements App\Core\Entity\EntityInterface.

src/Entity/MyEntity.php
namespace App\Entity;

use App\Repository\MyEntityRepository;
use Doctrine\ORM\Mapping as ORM;
use App\Core\Entity\EntityInterface;

#[ORM\Entity(repositoryClass: MyEntityRepository::class)]
class MyEntity implements EntityInterface
{
    // ...
}

Generation

The generation is performed in CLI. These information are required:

  • The namespace of the repository (eg: MyEntityRepository)

Simply run php bin/console make:repository-query.

Each entity has its own repository query which is a service.

src/Repository/MyEntityRepositoryQuery
namespace App\Repository;

use App\Core\Repository\RepositoryQuery;
use Knp\Component\Pager\PaginatorInterface;

class MyEntityRepositoryQuery extends RepositoryQuery
{
    public function __construct(MyEntityRepository $repository, PaginatorInterface $paginator)
    {
        parent::__construct($repository, 'm', $paginator);
    }

    // Example of custom filter
    public function filterByFooBar(bool $foo, bool $bar): self
    {
        $this
            ->andWhere('.foo = :foo')
            ->andWhere('.bar = :bar')
            ->setParameter(':foo', $foo)
            ->setParameter(':bar', $bar);

        return $this;
    }
}

Usage

You are able to find entities in an easy way, without knowing the identification variable and without creating a query builder.

src/Controller/FooController.php
namespace App\Controller;

use App\Repository\MyEntityRepositoryQuery
use Symfony\Component\HttpFoundation\Response;

class FooController
{
    public function foo(MyEntityRepositoryQuery $query): Response
    {
        $entities = $query->create()->find();
        $entity = $query->create()->findOne();

        // Filtered and sorted entities
        $entities = $query->create()
            ->orderBy('.id', 'DESC')
            ->where('.isPublished = true')
            ->find();

        // ...
    }
}

Custom methods

// ...

class MyEntityRepositoryQuery extends RepositoryQuery
{
    // ...

    public function filterByFooBar(bool $foo, bool $bar): self
    {
        $this
            ->andWhere('.foo = :foo')
            ->andWhere('.bar = :bar')
            ->setParameter(':foo', $foo)
            ->setParameter(':bar', $bar);

        return $this;
    }
}
$entities = $query->create()
    ->filterByFoo($foo, $bar)
    ->find();

In the context of a CRUD, filters are applied using the method useFilters.
Integers, strings and booleans are automatically processed. Other types are passed to the method filterHandler.

You have to override it to manage them, example:

// ...

use App\Entity\Something;

class MyEntityRepositoryQuery extends RepositoryQuery
{
    // ...

    public function filterHandler(string $name, $value): self
    {
        if ($name === 'something' && $value instanceof Something) {
            $this
                ->join('something', 's')
                ->andWhere('s.id = :something')
                ->setParameter('something', $value->getId())
            ;
        }
    }
}

You can also force filterHandler te be used for specific filter field:

// ...

class MyEntityRepositoryQuery extends RepositoryQuery
{
    public function __construct(Repository $repository, PaginatorInterface $paginator)
    {
        // ...

        $this->addForcedFilterHandler('foo');
    }

    public function filterHandler(string $name, $value): self
    {
        // ...

        if ($name === 'foo) {
            // ...
        }
    }

}

Pager

You can paginate entities (Knp\Component\Pager\Pagination\PaginationInterface):

$pager = $query->create()->paginate($page, $maxPerPage);