dualmedia/doctrine-query-creator
Installation Add the package via Composer:
composer require dualmedia/doctrine-query-creator
Ensure your project uses Doctrine ORM (Laravel's Eloquent is not compatible—use native Doctrine entities).
First Use Case
Convert a simple criteria array into a QueryBuilder:
use Dualmedia\DoctrineQueryCreator\QueryCreator;
$criteria = [
'where' => [
['field' => 'name', 'operator' => '=', 'value' => 'John'],
['field' => 'age', 'operator' => '>', 'value' => 30],
],
'orderBy' => ['field' => 'createdAt', 'direction' => 'DESC'],
];
$queryCreator = new QueryCreator($entityManager->getClassMetadata('App\Entity\User'));
$queryBuilder = $queryCreator->createQueryBuilder($criteria);
$results = $queryBuilder->getQuery()->getResult();
Where to Look First
QueryCreator class: Core logic for building queries.createQueryBuilder() method: Accepts criteria arrays and returns a QueryBuilder.Dynamic Filtering Use criteria arrays to build flexible queries (e.g., admin panels, search APIs):
$criteria = [
'where' => [
['field' => 'status', 'operator' => 'IN', 'value' => ['active', 'pending']],
['field' => 'deletedAt', 'operator' => 'IS NULL'],
],
];
Integration with Laravel Controllers Wrap the package in a service class to abstract Doctrine usage:
class UserQueryService {
public function __construct(private EntityManager $em) {}
public function findByCriteria(array $criteria): array {
$creator = new QueryCreator($this->em->getClassMetadata(User::class));
return $creator->createQueryBuilder($criteria)->getQuery()->getResult();
}
}
Pagination Support
Extend the criteria to include limit/offset:
$criteria = [
'limit' => 10,
'offset' => 20,
// ... other criteria
];
$queryBuilder = $queryCreator->createQueryBuilder($criteria);
Reusable Criteria Builders Create helper methods for common queries:
public function getActiveUsersCriteria(): array {
return [
'where' => [['field' => 'status', 'operator' => '=', 'value' => 'active']],
'orderBy' => [['field' => 'name', 'direction' => 'ASC']],
];
}
QueryCreator to avoid runtime errors.DISTINCT in criteria for large datasets:
$criteria = ['distinct' => true, /* ... */];
$criteria = [
'joins' => [
['join' => 'user.orders', 'alias' => 'o', 'condition' => 'o.status = :status'],
],
'parameters' => ['status' => 'shipped'],
];
Entity Metadata Dependency
QueryCreator requires ClassMetadata upfront. If the entity changes (e.g., new fields), queries may fail.$metadata = $em->getMetadataFactory()->getMetadataFor('App\Entity\User');
Operator Limitations
LIKE, BETWEEN) are supported by default.$queryBuilder->andWhere('u.name LIKE :name');
$queryBuilder->setParameter('name', '%John%');
Case Sensitivity
created_at vs. createdAt).Nested Criteria
QueryBuilder.$queryBuilder->getQuery()->getSQL(); // Inspect the generated SQL
dd($criteria); // Check for typos or invalid operators
Custom Operators
Extend the QueryCreator to handle custom logic:
$queryCreator->addCustomOperator('CUSTOM', function ($field, $value) use ($qb) {
$qb->andWhere("UPPER($field) = UPPER(:value)");
$qb->setParameter('value', $value);
});
Plugin System Create a plugin interface to add pre/post-processing:
interface QueryPlugin {
public function apply(QueryBuilder $qb, array $criteria);
}
Laravel-Specific Adaptations
use Doctrine\ORM\QueryBuilder;
$queryBuilder = $this->getDoctrineQueryBuilder();
QueryCreator as a singleton for global access.AND for where clauses), but override them in criteria if needed:
$criteria = [
'where' => [
['field' => 'name', 'operator' => '=', 'value' => 'John'],
['field' => 'age', 'operator' => '>', 'value' => 30, 'group' => 'OR'], // Custom group
],
];
How can I help you explore Laravel packages today?