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 Qb Filter Laravel Package

andrii-mz/doctrine-qb-filter

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require andrii-mz/doctrine-qb-filter
    

    Ensure your project uses Doctrine ORM (^2.7) and Symfony components (^4.1 or ^5.1).

  2. Basic Usage: Define a FilterRequest object (or extend it) to structure your filters:

    use AndriiMz\DoctrineQbFilter\FilterRequest;
    
    $filter = new FilterRequest();
    $filter->filter['name'] = 'John'; // Exact match
    $filter->filter['age']['gt'] = 25; // Greater than
    
  3. First Query: Inject the QueryFilter service (via DI container) and execute:

    $queryFilter = $container->get('andrii_mz.doctrine_qb_filter.query_filter');
    $result = $queryFilter->getResults(User::class, $filter);
    $users = $result->items; // Filtered results
    
  4. Key Files:

    • FilterRequest.php: Core filter structure.
    • QueryFilter.php: Main service class.
    • FilterBuilder.php: Handles filter logic (extend for custom rules).

Implementation Patterns

Common Workflows

  1. Dynamic Filtering: Use FilterRequest to build reusable filter logic:

    $filter = new FilterRequest();
    $filter->filter['status'] = ['active', 'pending']; // IN clause
    $filter->filter['created_at']['between'] = ['2023-01-01', '2023-12-31'];
    
  2. Integration with Controllers: Bind filter input to FilterRequest in a controller:

    public function index(Request $request, QueryFilter $queryFilter) {
        $filter = (new FilterRequest())->hydrate($request->query->all());
        return $queryFilter->getResults(User::class, $filter);
    }
    
  3. Nested Relationships: Filter on related entities (e.g., User with Task):

    $filter->filter['task']['priority'] = 'high'; // Joins + WHERE
    $filter->filter['task']['id']['is_not_null'] = true;
    
  4. Pagination: Combine with Doctrine Paginator:

    $result = $queryFilter->getResults(User::class, $filter, 10, 1); // 10 items/page, page 1
    
  5. Custom Filter Rules: Extend FilterBuilder to add domain-specific logic:

    class CustomFilterBuilder extends FilterBuilder {
        protected function buildCustomRule($field, $operator, $value) {
            // Add logic for 'custom_operator'
        }
    }
    

Integration Tips

  • Symfony Forms: Bind FilterRequest to form components for UI-driven filtering.
  • APIs: Use FilterRequest with API platforms (e.g., Symfony API Platform) for query params.
  • Caching: Cache filtered results if filters are static (e.g., dashboard widgets).
  • Validation: Validate FilterRequest inputs early (e.g., with Symfony Validator).

Gotchas and Tips

Pitfalls

  1. Operator Limitations:

    • Only supports basic operators (=, !=, >, <, IN, IS NULL, etc.).
    • Workaround: Extend FilterBuilder for custom operators (e.g., LIKE, REGEXP).
  2. Performance:

    • Complex nested filters (e.g., deep joins) may degrade performance.
    • Tip: Use fetch="LAZY" for large datasets or add DISTINCT manually.
  3. Case Sensitivity:

    • String comparisons are case-sensitive by default.
    • Fix: Use LOWER() in custom filter rules:
      $qb->expr()->eq('LOWER(u.name)', ':name')->setParameter('name', strtolower($value));
      
  4. Doctrine Events:

    • Filters run after lifecycle callbacks (e.g., @PrePersist). Avoid filtering on transient entities.
  5. Proprietary License:

    • Ensure compliance if using in commercial projects (check LICENSE file).

Debugging

  • Query Logging: Enable Doctrine logging to inspect generated SQL:
    $entityManager->getConnection()->getConfiguration()->setSQLLogger(new \Doctrine\DBAL\Logging\EchoSQLLogger());
    
  • Filter Validation: Add debug output for invalid operators:
    if (!$this->supportsOperator($operator)) {
        throw new \InvalidArgumentException("Operator '$operator' not supported for field '$field'");
    }
    

Extension Points

  1. Custom Filter Classes: Create filter-specific classes (e.g., DateFilterRequest) to enforce types:

    class DateFilterRequest extends FilterRequest {
        public function __construct() {
            $this->filter['created_at']['between'] = null; // Predefined field
        }
    }
    
  2. Override FilterBuilder: Subclass FilterBuilder to modify default behavior:

    services:
        andrii_mz.doctrine_qb_filter.filter_builder:
            class: App\Filter\CustomFilterBuilder
            public: true
    
  3. Add Metadata: Use Symfony PropertyInfo to auto-detect filterable fields:

    $propertyInfo = new PropertyInfo();
    $filterableFields = $propertyInfo->getTypes(User::class);
    
  4. Testing: Mock QueryFilter in tests:

    $queryFilter = $this->createMock(QueryFilter::class);
    $queryFilter->method('getResults')->willReturn(new ResultSet([$user], 1));
    
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.
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver