Clean query building using Criteria

  • avatar
  • 150 Views
  • 1 Like
  • 5 mins read

Criteria is a framework-agnostic PHP package that simplifies the use of the criteria pattern for filtering, sorting, and paginating data. It helps separate query logic from repositories, making the codebase easier to maintain and extend over time. By using Criteria, developers can handle complex querying needs without spreading filter logic across different parts of the application.

The package has recently been updated with several improvements. It now includes a cleanup of unused classes and files, a clearer usage structure, and the use of readonly classes to take advantage of PHP language features that improve safety and consistency. These changes make the package easier to work with, reduce potential bugs, and offer a more stable and consistent experience during development.

Prerequisites

Take a look on how to install Composer 2 on your computer to manage packages and its dependencies.

Installation

Assuming that Composer is already installed, you can include the package using Composer:

composer require hibit-dev/criteria

Generating criteria

A specific criteria must be created for each use case. It extends the shared domain logic found in the abstract Criteria implementation, which standardizes how filtering, sorting, and pagination are applied. This ensures that each query follows a consistent pattern while allowing flexibility for different filtering needs.

In this example, UserSearchCriteria is designed to handle filtering by name and email, while accepting CriteriaPagination and CriteriaSort to manage pagination and sorting. The static create() method builds a fully constructed criteria object.

use Hibit\\Criteria;
use Hibit\\CriteriaPagination;
use Hibit\\CriteriaSort;

final readonly class UserSearchCriteria extends Criteria
{
public ?string $name;
public ?string $email;

public static function create(
CriteriaPagination $pagination,
CriteriaSort $sort,
?string $name = null,
?string $email = null,
): UserSearchCriteria {
$criteria = new self($pagination, $sort);

$criteria->name = $name;
$criteria->email = $email;

return $criteria;
}
}

Marking the class as readonly ensures that the criteria object cannot be modified after creation, maintaining consistency and preventing unwanted changes during processing.

Pagination

The CriteriaPagination class is responsible for managing pagination. The create() method is used to easily construct a pagination object, where you can specify the limit and offset values (defaulting to 10 and 0 if not specified).

// Default Pagination: limit=10, offset=0
CriteriaPagination::create()

// Pagination: limit=10 (default), offset=10
CriteriaPagination::create(null, 10)

// Pagination: limit=20, offset=0 (default)
CriteriaPagination::create(20)

// Pagination: limit=20, offset=20
CriteriaPagination::create(20, 20)

The first value represents the limit (items per page), and the second value represents the offset (the starting point for the results). This approach ensures flexibility and ease of use when handling pagination in queries.

Sorting

The CriteriaSort class manages the sorting of query results. It works with the create() method to specify the field by which to sort the results, as well as the sorting direction (ascending or descending).

// Sorting: created_at DESC (default)
CriteriaSort::create('created_at')

// Sorting: created_at ASC
CriteriaSort::create('created_at', CriteriaSortDirection::ASC)

// Sorting: name DESC
CriteriaSort::create('name', CriteriaSortDirection::DESC)

This class helps maintain a consistent sorting approach throughout the application.

Integrating Criteria

Once a custom criteria class is defined, it can be passed into the repository to filter, sort, and paginate the data accordingly. The repository is where the actual query-building happens, using the criteria object to structure the database query. This keeps the filtering, sorting, and pagination logic separate from the rest of the application, making the code cleaner and easier to maintain.

use Hibit\\CriteriaPagination;
use Hibit\\CriteriaSort;
use Hibit\\CriteriaSortDirection;

class UserRepository
{
public function searchByCriteria(UserSearchCriteria $criteria): array
{
// Start query builder to apply filtering

if ($criteria->name !== null) {
// Apply name filter: $criteria->name
}

if ($criteria->email !== null) {
// Apply email filter: $criteria->email
}

if ($criteria->pagination !== null) {
// Apply limit: $criteria->pagination->limit
// Apply offset: $criteria->pagination->offset
}

if ($criteria->sort) {
// Apply sorting field: $criteria->sort->field->value()
// Apply sorting direction: $criteria->sort->direction->value()
}

// Execute the query and return the results
}
}

Note that all values can be nullable when constructing the query within the repository.

Using Criteria

To use the criteria in your repository, create an instance of the criteria class with the necessary filters, pagination, and sorting. Then, pass the criteria object to the repository method, which will apply it to the query.

use Hibit\\CriteriaPagination;
use Hibit\\CriteriaSort;
use Hibit\\CriteriaSortDirection;

class CriteriaTestClass
{
public function __invoke(UserRepository $userRepository): array
{
return $userRepository->searchByCriteria(
UserSearchCriteria::create(
CriteriaPagination::create(), // Default pagination
CriteriaSort::create('created_at', CriteriaSortDirection::DESC),
'John'
)
);
}
}

This approach ensures that filtering, sorting, and pagination are easily maintained and reused throughout the application.

Conclusion

The updated criteria package provides a cleaner, more modern way to manage query parameters in PHP. By relying on readonly classes, simplified structure, and improved defaults, it helps teams reduce boilerplate, avoid bugs, and keep code focused.

Credits

Official GitHub: https://github.com/hibit-dev/criteria

 Join Our Monthly Newsletter

Get the latest news and popular articles to your inbox every month

We never send SPAM nor unsolicited emails

0 Comments

Leave a Reply

Your email address will not be published.

Replying to the message: View original

Hey visitor! Unlock access to featured articles, remove ads and much more - it's free.