Symfony 5 – Repository Class extend from custom BaseRepository Class instead of ServiceEntityRepository

Lets say we have two Repository classes:

class CarrierRepository extends ServiceEntityRepository
{
    const ENTITY = 'carrier';

    /** @var PaginatorInterface $paginator */
    private $paginator;

    public function __construct(ManagerRegistry $registry, PaginatorInterface $paginator)
    {
        $this->paginator = $paginator;
        parent::__construct($registry, Carrier::class);
    }
.
.
.

class LocationRepository extends ServiceEntityRepository
{
    const ENTITY = 'location';

    /** @var PaginatorInterface $paginator */
    private $paginator;

    public function __construct(ManagerRegistry $registry, PaginatorInterface $paginator)
    {
        $this->paginator = $paginator;
        parent::__construct($registry, Location::class);
    }
.
.
.

And in both of these repository classes we have the same logic like this:

    public function search(array $searchParams)
    {
        $parameters = [];
        $qb = $this->createQueryBuilder(self::ENTITY);

        foreach ($searchParams['data'] as $key => $searchParam) {

            if (!empty($searchParam['param'])) {
                $entity = self::ENTITY;
                $operator = 'LIKE';
                $column = $searchParam['key'];
                $parameters[$searchParam['key']] = '%'.$searchParam['param'].'%';
.
.
.

As you can see, both Repository classes have the same dependencies and the same logic – except the entity class – in one class it is "carrier" and in the other it is "location".
I think it will be a good idea to merge this into a BaseRepository class like this:

class BaseRepository extends ServiceEntityRepository
{
    private $entity;

    /** @var PaginatorInterface $paginator */
    private $paginator;

    public function __construct($entity, ManagerRegistry $registry, PaginatorInterface $paginator)
    {
        $this->entity = $entity;
        $this->paginator = $paginator;
        parent::__construct($registry, $this->entity);
    }

    public function search(array $searchParams)
    {
        $parameters = [];
        $qb = $this->createQueryBuilder(self::ENTITY);

        foreach ($searchParams['data'] as $key => $searchParam) {

            if (!empty($searchParam['param'])) {
                $entity = self::ENTITY;
                $operator = 'LIKE';
                $column = $searchParam['key'];
                $parameters[$searchParam['key']] = '%'.$searchParam['param'].'%';
.
.
.

and to extend my other both repositories instead of

ServiceEntityRepository

with my BaseRepository like this (example for the CarrierRepository):

class CarrierRepository extends BaseRepository
{
    const ENTITY = 'carrier';

    /** @var PaginatorInterface $paginator */
    private $paginator;

    public function __construct(ManagerRegistry $registry, PaginatorInterface $paginator)
    {
        $this->paginator = $paginator;
        parent::__construct(Carrier::class, $registry, $paginator);
    }
.
.
.

This does not work – it will give me this error:

Cannot autowire service "AppRepositoryBaseRepository": argument
"$entity" of method "__construct()" has no type-hint, you should
configure its value explicitly.

Question:
How can I implement a BaseRepository for all my EntityRepositories that uses the same properties and logic, so I do not have to implement the whole logic in all my Repository classes again and again?
I want to have a Base Repository in which is the whole logic and all of my Repository classes can use the same code.

Source: Symfony Questions

Was this helpful?

0 / 0

Leave a Reply 0

Your email address will not be published. Required fields are marked *