# Repository Query

A Repository query is an abstraction of the doctrine repository.

## Requirement

Entities must implements `App\Core\Entity\EntityInterface`.

```php-inline title="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.


```php-inline title="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.

```php-inline title="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

```php-inline
// ...

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;
    }
}
```

```php-inline
$entities = $query->create()
    ->filterByFoo($foo, $bar)
    ->find();
```

In the context of a CRUD, filters are applied using [the method `useFilters`](https://gitnet.fr/murph/murph-core/src/branch/master/src/core/Repository/RepositoryQuery.php#L78-L99).  
Integers, strings and booleans are automatically processed. Other types are passed to [the method `filterHandler`](https://gitnet.fr/murph/murph-core/src/branch/master/src/core/Repository/RepositoryQuery.php#L122-L124).

You have to override it to manage them, example:

```php-inline
// ...

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:

```php-inline
// ...

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`):

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