PHP code example of ttskch / doctrine-orm-criteria

1. Go to this page and download the library: Download ttskch/doctrine-orm-criteria library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

ttskch / doctrine-orm-criteria example snippets


$qb = (new CriteriaAwareness($fooRepository->createQueryBuilder('f')))
    ->addCriteria(new IsPublic(), 'f')
    ->addCriteria(new IsAccessibleBy($user), 'f')
    ->addCriteria(new CategoryIs($category), 'f')
    ->addCriteria(new OrderByRandom(), 'f')
    ->getQueryBuilder()
;
$foos = $qb->getQuery()->getResult();

// Or, using the Repository integration:

$foos = $fooRepository->findByCriteria([
    new IsPublic(),
    new IsAccessibleBy($user),
    new CategoryIs($category),
    new OrderByRandom(),
]);

final readonly class IsPublic implements CriteriaInterface
{
    public ?\DateTimeInterface $at;

    public function __construct(?\DateTimeInterface $at = null)
    {
        $this->at = $at ?? new \DateTimeImmutable();
    }

    public function apply(QueryBuilder $qb, string $alias): void
    {
        $qb
            ->andWhere("$alias.state = :state")
            ->andWhere($qb->expr()->andX(
                $qb->expr()->orX(
                    "$alias.openedAt IS NULL",
                    "$alias.openedAt <= :at",
                ),
                $qb->expr()->orX(
                    "$alias.closedAt IS NULL",
                    "$alias.closedAt > :at",
                ),
            ))
            ->setParameter('state', Foo::STATE_PUBLIC)
            ->setParameter('at', $this->at)
        ;
    }
}

use App\Repository\Criteria\Foo\IsPublic;
use Ttskch\DoctrineOrmCriteria\CriteriaAwareness;

$qb = (new CriteriaAwareness($fooRepository->createQueryBuilder('f')))
    ->addCriteria(new IsPublic(), 'f')
    ->getQueryBuilder()
;



declare(strict_types=1);

namespace App\Repository\Criteria\Foo;

final readonly class IsPublic implements CriteriaInterface
{
    public ?\DateTimeInterface $at;

    public function __construct(?\DateTimeInterface $at = null)
    {
        $this->at = $at ?? new \DateTimeImmutable();
    }

    public function apply(QueryBuilder $qb, string $alias): void
    {
        $qb
            ->andWhere("$alias.state = :state")
            ->andWhere($qb->expr()->andX(
                $qb->expr()->orX(
                    "$alias.openedAt IS NULL",
                    "$alias.openedAt <= :at",
                ),
                $qb->expr()->orX(
                    "$alias.closedAt IS NULL",
                    "$alias.closedAt > :at",
                ),
            ))
            ->setParameter('state', Foo::STATE_PUBLIC)
            ->setParameter('at', $this->at)
        ;
    }
}



declare(strict_types=1);

namespace App\Repository\Criteria\Foo;

use App\Entity\User;
use Doctrine\ORM\QueryBuilder;
use Ttskch\DoctrineOrmCriteria\Criteria\CriteriaInterface;
use Ttskch\DoctrineOrmCriteria\Criteria\Andx;
use Ttskch\DoctrineOrmCriteria\Criteria\Orx;

final readonly class IsViewable implements CriteriaInterface
{
    public ?\DateTimeInterface $at;

    public function __construct(
        public User $me,
        ?\DateTimeInterface $at = null,
    ) {
        $this->at = $at ?? new \DateTimeImmutable();
    }

    public function apply(QueryBuilder $qb, string $alias): void
    {
        (new Andx([
            new Orx([
                new IsPublic($this->at),
                ...array_map(fn (string $category) => new CategoryIs($category), Foo::PUBLIC_CATEGORIES),
            ]),
            new IsAccessibleBy($this->me),
        ]))->apply($qb, $alias);
    }
}



declare(strict_types=1);

namespace App\Repository\Criteria\Foo;

use App\Entity\User;
use Doctrine\ORM\QueryBuilder;
use Ttskch\DoctrineOrmCriteria\Criteria\CriteriaInterface;
use Ttskch\DoctrineOrmCriteria\Criteria\Traits\JoinTrait;

final readonly class IsAccessibleBy implements CriteriaInterface
{
    use JoinTrait;

    private const string CRITERIA_KEY = 'Foo_IsAccessibleBy'; // some unique key

    public function __construct(public User $me)
    {
    }

    public function apply(QueryBuilder $qb, string $alias): void
    {
        $userAlias = sprintf('%s_%s_user', self::CRITERIA_KEY, $alias);

        $this->leftJoin($qb, sprintf('%s.user', $alias), $userAlias);

        $qb
            ->andWhere(sprintf('%s = :user', $userAlias))
            ->setParameter('user', $this->me)
        ;
    }
}

$foos = $fooRepository->findByCriteria([
    new IsPublic(),
    new IsAccessibleBy($user),
    new CategoryIs($category),
    new OrderByRandom(),
]);

\PHPStan\dumpType($foos); // Dumped type: array<App\Entity\Foo>

$foo = $fooRepository->findOneByCriteria([
    new IsPublic(),
    new IsAccessibleBy($user),
    new CategoryIs($category),
    new OrderByRandom(),
]);

\PHPStan\dumpType($foo); // Dumped type: App\Entity\Foo|null

$count = $fooRepository->countByCriteria([
    new IsPublic(),
    new IsAccessibleBy($user),
    new CategoryIs($category),
]);

\PHPStan\dumpType($count); // Dumped type: int