Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Doctrine Query Document Laravel Package

dbstudios/doctrine-query-document

Build Doctrine DQL filters from a simple array “query document”. Apply conditions to an existing QueryBuilder (from/select required), auto-bind positional parameters, traverse relations via dot notation, and query JSON fields (MySQL 5.7+).

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require dbstudios/doctrine-query-document
    

    Ensure your project uses Doctrine ORM (v2.5+ recommended).

  2. First Use Case: Replace traditional DQL WHERE clauses with MongoDB-style query documents.

    use Doctrine\Common\Persistence\ObjectManager;
    use DbStudios\DoctrineQueryDocument\QueryManager;
    
    $manager = new QueryManager($objectManager);
    $qb = $objectManager->createQueryBuilder()
        ->from('App\Entity\User', 'u')
        ->select('u');
    
    $manager->apply($qb, [
        'name' => 'John',
        'age'  => ['$gt' => 25]
    ]);
    
    // Resulting DQL: WHERE u.name = ?0 AND u.age > ?1
    
  3. Key Files:

    • QueryManager (core class)
    • DoctrineQueryDocumentException (error handling)
    • src/QueryManager.php (extension points)

Implementation Patterns

Core Workflow

  1. Query Construction:

    $query = [
        'field1' => 'value',
        'field2' => ['$in' => [1, 2, 3]],
        'field3' => ['$exists' => true]
    ];
    $manager->apply($qb, $query);
    
  2. Relationship Handling: Use dot notation for joins/filters:

    $manager->apply($qb, [
        'posts.title' => 'Hello',
        'author.name' => ['$like' => '%Doe%']
    ]);
    
  3. Parameter Binding: All values auto-convert to positional parameters:

    $manager->apply($qb, ['createdAt' => ['$gt' => new \DateTime()]]);
    

Integration Tips

  • Hybrid Queries: Mix with native DQL:

    $qb->andWhere('u.status = :status')
       ->setParameter('status', 'active');
    $manager->apply($qb, ['name' => 'Admin']); // Appends to existing WHERE
    
  • Repository Layer:

    public function findByDocument(array $query) {
        $qb = $this->createQueryBuilder('u');
        $manager = new QueryManager($this->getEntityManager());
        $manager->apply($qb, $query);
        return $qb->getQuery()->getResult();
    }
    
  • Dynamic Fields: Use select() with query documents:

    $manager->apply($qb, [], ['fields' => ['name', 'email']]);
    // Result: SELECT u.name, u.email FROM ...
    

Gotchas and Tips

Pitfalls

  1. Missing from/select: Throws DoctrineQueryDocumentException if required clauses are absent. Fix: Always call createQueryBuilder()->from()->select().

  2. Unsupported Operators: Only $eq, $gt, $lt, $in, $like, $exists are implemented. Workaround: Use raw DQL for unsupported ops (e.g., $regex).

  3. Parameter Collisions: Manual parameters (e.g., setParameter()) may conflict with auto-bound values. Tip: Prefix manual params (e.g., :manual_*).

  4. Nested Relationships: Deep dot notation (e.g., user.profile.address.city) may fail if intermediate joins lack JOIN clauses. Solution: Pre-join entities or use innerJoin() explicitly.

Debugging

  • DQL Output:
    echo $qb->getDQL(); // Verify generated SQL
    
  • Parameter Binding:
    $qb->getQuery()->getParameters(); // Inspect bound params
    

Extension Points

  1. Custom Operators: Extend QueryManager to support new operators:

    class CustomQueryManager extends QueryManager {
        protected function registerOperators() {
            $this->operators['$custom'] = function($field, $value) {
                return "CUSTOM_FUNCTION($field, :$field)";
            };
        }
    }
    
  2. Query Modifiers: Override apply() to pre/post-process queries:

    $manager->apply($qb, $query, ['modifier' => function($qb) {
        $qb->andWhere('u.deleted = 0');
    }]);
    
  3. Type Casting: Handle custom types (e.g., UUIDs) by extending QueryManager::castValue().

Performance Tips

  • Batch Queries: Reuse QueryManager instances for multiple queries.
  • Index Awareness: Ensure query fields match database indexes (e.g., WHERE user.id IN (...)).
  • Avoid $like on Large Fields: Use $regex with anchors (/^pattern/) instead.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor