dromru / iterable-dbal
Набор классов для разбиения пакетных sql-запросов на раздельные.
Installs: 8 343
Dependents: 0
Suggesters: 0
Security: 0
Stars: 4
Watchers: 4
Forks: 0
Open Issues: 0
Requires
- php: >=7.4
Requires (Dev)
- friendsofphp/php-cs-fixer: 2.18.5
- phpmd/phpmd: ^2.6
- phpstan/extension-installer: ^1.0
- phpstan/phpstan: ^0.12.32
- phpstan/phpstan-deprecation-rules: ^0.12.2
- phpunit/phpunit: ^9.5.20
- squizlabs/php_codesniffer: ^3.5
README
Проблема
Зачастую код получения данных пачками из БД перемешивается с логикой обработки этих данных. Такой код часто дублируется и усложняет поддержку.
Решение
iterable-dbal
- пакет, который предоставляет набор классов для разбиения пакетных sql-запросов на раздельные.
Приспособлен для использования в связке с doctrine/dbal.
P.S. Реализован с использованием генераторов.
Примеры использования
Допустим необходимо итерировать по существующим записям в БД с идентификаторами в промежутке от 1 до 1 000 000 000.
Когда весь 1 000 000 000 из БД в память не влезает (жирный запрос), можно
использовать \Drom\IterableUtils\Dbal\BatchedMinMaxQueryIterator
для того чтобы выполнить N облегчённых запросов - эта
логика скрыта внутри итератора.
/** * @var \Doctrine\DBAL\Connection $connection */ $iterator = new \Drom\IterableUtils\Dbal\BatchedMinMaxQueryIterator( $batchSize = 1000, \Closure::fromCallable([$connection, 'fetchFirstColumn']), <<<'SQL' SELECT id FROM `test`.`sample_table` WHERE field1 IN (:param1) WHERE id BETWEEN :minId AND :maxId SQL, [ 'minId' => 1, 'maxId' => 1_000_000_000, 'field1' => [1, 2, 3], ], [ 'minId' => \Doctrine\DBAL\ParameterType::INTEGER, 'maxId' => \Doctrine\DBAL\ParameterType::INTEGER, 'field1' => \Doctrine\DBAL\Connection::PARAM_INT_ARRAY, ] ); foreach ($iterator as $id) { echo PHP_EOL . $id; }
Если требуется итерировать по существующей коллекции идентификаторов, но необходимо получать набор связанных данных, то можно
использовать \Drom\IterableUtils\Dbal\BatchedIdsQueryIterator
для того чтобы выполнить N облегчённых запросов.
$ids = [1, 2, /* ... */, 1_000_000_000]; /** * @var \Doctrine\DBAL\Connection $connection */ $iterator = new \Drom\IterableUtils\Dbal\BatchedIdsQueryIterator( $batchSize = 1000, \Closure::fromCallable([$connection, 'fetchAllAssociative']), <<<'SQL' SELECT * FROM `test`.`sample_table` WHERE field1 = :param1 WHERE id in (:ids) SQL, [ 'ids' => $ids, 'param1' => 1, ], [ 'ids' => \Doctrine\DBAL\Connection::PARAM_INT_ARRAY, 'param1' => \Doctrine\DBAL\ParameterType::INTEGER, ] ); foreach ($iterator as $item) { echo PHP_EOL; print_r($item); echo PHP_EOL; }