atlance/http-doctrine-dbal-filter

dbal dynamic filter from http query

dev-main 2023-10-09 01:06 UTC

This package is auto-updated.

Last update: 2024-04-09 02:21:57 UTC


README

Scrutinizer Code Quality Code Coverage Build Status Code Intelligence Status GitHub Maintainability Psalm coverage composer.lock PHP analyze & tests

Analogue of atlance/http-doctrine-orm-filter for DBAL and of course without validation.

Simple example:

<?php # src/Fetcher.php

declare(strict_types=1);

namespace App;

use Atlance\HttpDbalFilter\Filter;
use Atlance\HttpDbalFilter\Query\Configuration;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\ForwardCompatibility\Result;
use Doctrine\DBAL\Query\QueryBuilder;

final class Fetcher
{
    public function __construct(
        private readonly Connection $connection,
        private readonly Filter $filter
    ) {
    }

    /**
     * @throws \Doctrine\DBAL\Driver\Exception
     * @throws \Doctrine\DBAL\Exception
     */
    public function fetch(Configuration $conditions): mixed
    {
        return $this->executeQuery($this->buildQuery($conditions))->fetchOne();
    }

    private function buildQuery(Configuration $conditions): QueryBuilder
    {
        $qb = $this->connection->createQueryBuilder();
        $qb->select('COUNT(DISTINCT(users.id))')
            ->from('users', 'users')
            ->leftJoin('users', 'users_cards', 'uc', 'uc.user_id = users.id')
            ->leftJoin('uc', 'banking_cards', 'cards', 'uc.card_id = cards.id')
            ->leftJoin('users', 'phones', 'phones', 'phones.user_id = users.id')
            ->leftJoin('users', 'passports', 'passport', 'passport.user_id = users.id');

        $this->filter->apply($qb, $conditions);

        return $qb;
    }

    /**
     * @throws \Doctrine\DBAL\Exception
     */
    private function executeQuery(QueryBuilder $qb): Result
    {
        $stmt = $qb->execute();
        if ($stmt instanceof Result) {
            return $stmt;
        }

        throw new \DomainException('this method works only with the select operator');
    }
}
<?php # src/FetcherFactory.php

declare(strict_types=1);

namespace App;

use Atlance\HttpDbalFilter\Filter;
use Atlance\HttpDbalFilter\Query\Expression\ConditionFactory;
use Doctrine\DBAL\DriverManager;
use Psr\SimpleCache\CacheInterface;

final class FetcherFactory
{
    public static function create(?CacheInterface $cache = null): Fetcher
    {
        return new Fetcher(
            DriverManager::getConnection([
                'driver' => 'pdo_sqlite',
                'path' => \dirname(__DIR__) . '/storage/db.sqlite',
            ]),
            new Filter(new ConditionFactory($cache))
        );
    }
}
<?php # public/index.php

declare(strict_types=1);

require_once __DIR__ . '/../vendor/autoload.php';

use Atlance\HttpDbalFilter\Query\Configuration;
use App\FetcherFactory;

// as example, from http query parameter: ?filter[eq][users_id]=1
$result = FetcherFactory::create()->fetch(
    Configuration::fromArray([
        'filter' => [
            'eq' => [
                'users_id' => 1,
            ],
        ],
    ])
);

var_dump($result);

More examples in tests.