alex-storozhenko / eloquent-criteria
Eloquent的轻量级Criteria构建器实现
Requires
- php: ^8.1
- illuminate/contracts: ^10.0
- illuminate/database: ^10.0
- spatie/laravel-package-tools: ^1.14.0
Requires (Dev)
- laravel/pint: ^1.13
- nunomaduro/collision: ^7.8
- nunomaduro/larastan: ^2.0.1
- orchestra/testbench: ^8.8
- pestphp/pest: ^2.0
- pestphp/pest-plugin-arch: ^2.3
- pestphp/pest-plugin-laravel: ^2.2
- phpstan/extension-installer: ^1.3
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.3
- spatie/laravel-ray: ^1.26
This package is auto-updated.
Last update: 2024-09-10 00:02:12 UTC
README
Eloquent Criteria
⚠️ 兼容性说明
请使用1.x.x版本以兼容Laravel 9
composer require alex-storozhenko/eloquent-criteria ^1.1
这是Eloquent Criteria Builder的轻量级实现。它就像LEGO®一样,为Eloquent Builder提供易于解耦和重用查询修饰符。
显然,主要目的是以指定的方式修改查询,因为Criteria与Eloquent scopes非常相似,只是它们可以在应用中以不同的方式应用,并以干净的方式封装更复杂的条件以及附加逻辑。
安装
您可以通过composer安装此包
composer require alex-storozhenko/eloquent-criteria
您可以使用以下命令发布配置文件
php artisan vendor:publish --tag="eloquent-criteria-config"
这是发布配置文件的内容
return [ /* |-------------------------------------------------------------------------- | Macro |-------------------------------------------------------------------------- | | This option controls the ability to add a macro to the eloquent builder, | which allows, when enabled, to add criteria builder functionality to the eloquent | at the global level | methods criteriaQuery(), apply() will be added | to the Eloquent through the macro | */ 'macro_enabled' => env('ELOQUENT_CRITERIA_MACRO_ENABLED', false), ];
用法
有几种方法可以开始使用Criteria Builder,其中之一是简单地启用宏并使其全局工作,只需将其添加到您的.env文件中
宏
ELOQUENT_CRITERIA_MACRO_ENABLED=true
或者更改配置文件eloquent-criteria.php
中的值
然后进行魔法操作
Criteria类
<?php declare(strict_types=1); namespace App\Criteria\User; use AlexStorozhenko\EloquentCriteria\Contracts\Criteria; use Illuminate\Database\Eloquent\Builder; class BannedUser implements Criteria { public function apply(Builder $builder): Builder { return $builder->whereNotNull('banned_at'); } }
并应用于查询
<?php declare(strict_types=1); ... use App\Criteria\User\BannedUser; ... User::criteriaQuery()->apply(new BannedUser())->paginate(); // or User::apply(new BannedUser())->paginate();
关注点
当然,如果您反对宏并且希望控制一切,那么有一个助手(关注点)供您使用
<?php declare(strict_types=1); namespace App\Models; use AlexStorozhenko\EloquentCriteria\Concerns\CriteriaQuery; use Illuminate\Foundation\Auth\User as Authenticatable; use AlexStorozhenko\EloquentCriteria\Concerns\CriteriaQuery; class User extends Authenticatable { use CriteriaQuery; }
然后再次操作
<?php declare(strict_types=1); ... use App\Criteria\User\BannedUser; ... User::criteriaQuery()->apply(new BannedUser())->paginate();
CriteriaModel
您也可以扩展您的模型
<?php declare(strict_types=1); namespace App\Models; use Illuminate\Auth\Authenticatable; use Illuminate\Auth\MustVerifyEmail; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract; use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract; use Illuminate\Foundation\Auth\Access\Authorizable; use AlexStorozhenko\EloquentCriteria\Model as CriteriaModel; class User extends CriteriaModel implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract { use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail; }
通过for()包装器
最后,如果您需要使Eloquent立即与Criteria兼容,是的,您可以
<?php declare(strict_types=1); ... use App\Criteria\User\BannedUser; use AlexStorozhenko\EloquentCriteria\CriteriaBuilder; ... CriteriaBuilder::for(User::query())->apply(new BannedUser())->paginate();
CriteriaChain
当然,您可以使用CriteriaChain来分组您的criteria并按链式应用它们,为此请使用CriteriaChain,它将所有传入的Criteria编译成可执行的查询修饰符链
<?php declare(strict_types=1); ... use App\Criteria\User\BannedUser; use AlexStorozhenko\EloquentCriteria\CriteriaBuilder; use AlexStorozhenko\EloquentCriteria\Support\CriteriaChain; use AlexStorozhenko\EloquentCriteria\Contracts\Criteria; ... $haveNotLastName = new class() implements Criteria { public function apply(Builder $builder): Builder { return $builder->whereNull('last_name'); } }; CriteriaBuilder::for(User::query())->apply(new CriteraChain(new BannedUser(), $hasNotLastName))->paginate();
乍一看,这似乎可以用Laravel中开箱即用的模型作用域来替换,是的,但如果您需要具有修饰符组,并且修饰符将基于在模型外定义的几个条件构建查询,这可能会使模型类过载。
例如,在以下情况下,我认为Criteria类比带有请求传递和条件应用的要求的模型作用域看起来要好得多,如果您想象这个逻辑可能会被其他条件扩展
<?php declare(strict_types=1); namespace App\Criteria\Common; use AlexStorozhenko\EloquentCriteria\Contracts\Criteria; use Illuminate\Database\Eloquent\Builder; use App\Criteria\Concern\HttpFilters; use App\DataObject\Filter; use Illuminate\Http\Request; class ByRequestFiltersCriteria implements Criteria { use HttpFilters; // Dirty job of parsing request query public function __construct(private readonly Request $request) {} public function apply(Builder $builder): Builder { /** @var Filter $filter */ foreach ($this->getFilters() as $filter) { $builder->{$filter->getMethod()}(...$filter->getMethodArguments()); } return $builder; } }
如您所见,Criteria Builder提供了绝对的使用灵活性,因此如何将其最佳地实现到您的应用程序架构中完全取决于您。
测试
composer test
变更日志
请参阅CHANGELOG以获取有关最近更改的更多信息。
贡献
请参阅CONTRIBUTING以获取详细信息。
安全漏洞
如果您发现任何安全问题,请将详细信息发至我的邮箱:a.storozhenko@live.com
致谢
许可
MIT许可(MIT)。请参阅许可文件以获取更多信息。