baethon/laravel-criteria

Minimal interface for criteria pattern

1.1.0 2023-01-31 18:00 UTC

This package is auto-updated.

Last update: 2024-03-29 03:44:42 UTC


README

Minimal implementation of criteria pattern for Laravel.

What is criteria?

Criteria is an implementation of \Baethon\LaravelCriteria\CriteriaInterface which is responsible for only one thing - modify Laravels query in a specified way.

This allows to decouple and re-use query modifiers.

Criteria are very similar to Eloquent scopes. The main difference is that they can be applied to different models across the application.

Installation

composer require baethon/laravel-criteria

Requirements

  • PHP >= 7.1

Laravel compatibility

This library has no dependencies to Laravel itself. It should work with all versions of Laravel.

Usage

First, you need to create an implementation of CriteriaInterface:

<?php

use Baethon\LaravelCriteria\CriteriaInterface;

class CompareCriteria implements CriteriaInterface
{
    private $field;

    private $value;

    public function __construct(string $field, string $value)
    {
        $this->field = $field;
        $this->value = $value;
    }

    public function apply($query)
    {
        $query->where($this->field, $this->value);
    }
}

Now, you can apply it to the query:

$query = User::query();

(new CompareCriteria('name', 'Jon'))->apply($query);

$jon = $query->first();

AppliesCriteria trait

To simplify things it's possible to use AppliesCriteria trait in a model.

use Baethon\LaravelCriteria\Traits\AppliesCriteria;

class User extends Model
{
    // model body stripped for better readability

    use AppliesCriteria;
}

$jon = User::query()
    ->apply(new CompareCriteria('name', 'Jon'))
    ->first();

Collections

The package provides collections which allow applying multiple criteria at once.

To apply group of criteria use \Baethon\LaravelCriteria\Collections\CriteriaCollection:

$jonSnow = User::query()
    ->apply(CriteriaCollection::create([
        new CompareCriteria('name', 'Jon'),
        new CompareCriteria('lastname', 'Snow'),
    ]))
    ->first();

// same result, without CriteriaCollection
$jonSnow = User::query()
    ->apply(new CompareCriteria('name', 'Jon'))
    ->apply(new CompareCriteria('lastname', 'Snow'))
    ->first();

If you need to be sure that all criteria will be fulfilled you can use CriteriaCollection::allOf():

User::query()
    ->apply(CriteriaCollection::allOf([
        new CompareCriteria('name', 'Jon'),
        new CompareCriteria('lastname', 'Snow'),
    ]));

// same as
User::query()
    ->where(function ($query) {
        $query->apply(new CompareCriteria('name', 'Jon'))
            ->apply(new CompareCriteria('lastname', 'Snow'));
    });

Also, you can group criteria using logical OR join:

User::query()
    ->apply(CriteriaCollection::oneOf([
        new CompareCriteria('name', 'Jon'),
        new CompareCriteria('lastname', 'Snow'),
    ]));

// same as
User::query()
    ->where(function ($query) {
        $query->where('name', 'Jon')
            ->orWhere('lastname', 'Snow');
    });

Testing

Run tests with:

./vendor/bin/phpunit

Changelog

Please see CHANGELOG for more information what has changed recently.

License

The MIT License (MIT). Please see License File for more information.