mjahn/eloquent-builder

v1.0.2 2019-09-04 22:56 UTC

This package is auto-updated.

Last update: 2024-09-29 05:55:23 UTC


README

Build Status Coverage Status StyleCI Latest Stable Version Total Downloads License

此包允许您基于请求参数构建优雅的查询。它极大地降低了查询和条件的复杂性,从而使您的代码更加清晰。

基本用法

假设您想获取具有以下请求参数的用户列表

//Get api/user/search?age_more_than=25&gender=male&has_published_post=true
[
    'age_more_than'  => '25',
    'gender'         => 'male',
    'has_published_post' => 'true',
]

旧版 代码中,遵循以下方法

<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function index(Request $request)
    {
        $users = User::where('is_active', true);

        if ($request->has('age_more_than')) {
            $users->where('age', '>', $request->age_more_than);
        }

        if ($request->has('gender')) {
            $users->where('gender', $request->gender);
        }

        // A User model may have an infinite numbers of Post(One-To-Many).
        if ($request->has('has_published_post')) {
            $users->where(function ($query) use ($request) {
                $query->whereHas('posts', function ($query) use ($request) {
                    $query->where('is_published', $request->has_published_post);
                });
            });
        }

        return $users->get();
    }
}

但是 在使用 EloquentBuilder 之后,上述代码重构如下

<?php

namespace App\Http\Controllers;

use App\User;
use EloquentBuilder;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function index(Request $request)
    {
        $users = EloquentBuilder::to(User::class, $request->all());

        return $users->get();
    }
}

您只需为要添加到查询中的每个参数定义 过滤器

提示:建议在发送到过滤器之前验证传入的请求。

提示:建议将过滤器放在查询字符串的 filter 键内部,如下所示: user/search?filter[age_more_than]=25&filter[gender]=male
然后以这种方式获取它们:$request->only('filter')

安装

Laravel

您可以通过 composer 安装此包

composer require mohammad-fouladgar/eloquent-builder

Laravel 5.5 使用包自动发现,因此您无需手动添加 ServiceProvider。

Laravel <= 5.4.x

如果您不使用自动发现,请将 ServiceProvider 添加到 config/app.php 文件中的 providers 数组

'providers' => [
  /*
   * Package Service Providers...
   */
  Fouladgar\EloquentBuilder\ServiceProvider::class,
],

并将 外观 添加到您的 config/app.php 文件

/*
|--------------------------------------------------------------------------
| Class Aliases
|--------------------------------------------------------------------------
*/
'aliases' => [
    "EloquentBuilder" => Fouladgar\EloquentBuilder\Facade::class,
]

Lumen

您可以通过 composer 安装此包

composer require mohammad-fouladgar/eloquent-builder

对于 Lumen,请将 LumenServiceProvider 添加到 bootstrap/app.php 文件

/*
|--------------------------------------------------------------------------
| Register Service Providers...
|--------------------------------------------------------------------------
*/

$app->register(\Fouladgar\EloquentBuilder\LumenServiceProvider::class);

要使用外观,您必须在 bootstrap/app.php 文件中取消注释 $app->withFacades();

取消注释此行后,您将启用 EloquentBuilder 外观

$app->withFacades();

发布配置文件

php artisan eloquent-builder:publish

并将配置添加到 bootstrap/app.php 文件

$app->configure('eloquent-builder');
...
$app->register(\Fouladgar\EloquentBuilder\LumenServiceProvider::class);

重要:这需要在注册服务提供商之前完成。

默认过滤器命名空间

所有过滤器的默认命名空间为 App\EloquentFilters,其基名为模型。例如,对于 User 模型,过滤器命名空间将是 App\EloquentFilters\User

使用配置文件

您可以选择使用以下方式发布配置文件

php artisan vendor:publish --provider="Fouladgar\EloquentBuilder\ServiceProvider" --tag="config"

并设置您模型过滤器所在的命名空间,该过滤器将位于

return [
    /*
     |--------------------------------------------------------------------------
     | Eloquent Filter Settings
     |--------------------------------------------------------------------------
     |
     | This is the namespace all you Eloquent Model Filters will reside
     |
     */
    'namespace' => 'App\\EloquentFilters\\',
];

定义一个过滤器

编写过滤器很简单。定义一个继承自 Fouladgar\EloquentBuilder\Support\Foundation\Contracts\Filter 抽象类的类。该类要求您实现一个方法: apply。根据需要,apply 方法可以添加 where 约束到查询。每个过滤器类都应该以单词 Filter 结尾。

例如,看一下下面定义的过滤器

<?php

namespace App\EloquentFilters\User;

use Fouladgar\EloquentBuilder\Support\Foundation\Contracts\Filter;
use Illuminate\Database\Eloquent\Builder;

class AgeMoreThanFilter extends Filter
{
    /**
     * Apply the age condition to the query.
     *
     * @param Builder $builder
     * @param mixed   $value
     *
     * @return Builder
     */
    public function apply(Builder $builder, $value): Builder
    {
        return $builder->where('age', '>', $value);
    }
}

提示:您还可以在过滤器中轻松使用 局部作用域。因为它们是查询构建器的实例。

授权过滤器

过滤器类还包含一个 authorize 方法。在此方法内,您可以检查认证用户是否有权应用给定的过滤器。例如,您可以确定用户是否有高级账户,可以应用 StatusFilter 以列出在线或离线人员

/**
 * Determine if the user is authorized to make this filter.
 *
 * @return bool
 */
 public function authorize(): bool
 {
     if(auth()->user()->hasPremiumAccount()){
        return true;
     }

    return false
 }

默认情况下,您无需实现 authorize 方法,并且过滤器将应用于您的查询构建器。如果 authorize 方法返回 false,将自动返回一个具有 403 状态码的 HTTP 响应。

忽略空值上的过滤器

如果过滤器参数包含 空值,则忽略过滤器。

假设您有一个这样的请求

//Get api/user/search?filter[name]&filter[gender]=null&filter[age_more_than]=''&filter[published_post]=true

EloquentBuilder::to(User::class,$request->only('filter'));

// filters result will be:
$filters = [
    'published_post'  => true
];

只有 "published_post" 过滤器会被应用于您的查询。

处理现有查询

您也可以选择处理现有查询。例如,考虑以下代码

<?php

namespace App\Http\Controllers;

use App\User;
use EloquentBuilder;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function index(Request $request)
    {
        $query = User::where('is_active', true);
        $users = EloquentBuilder::to($query, $request->all())
            ->where('city', 'london')
            ->paginate();

        return $users;
    }
}

作为依赖注入使用

假设您想将 EloquentBuilder 作为 DependencyInjection 用于 Repository

让我们举一个例子。我们有一个如下的示例 UserRepository

<?php

namespace App\Repositories;

use App\User;
use Fouladgar\EloquentBuilder\EloquentBuilder;

class UserRepository extends BaseRepository
{
    
    public function __construct(EloquentBuilder $eloquentBuilder)
    {
        $this->eloquentBuilder = $eloquentBuilder;
        $this->makeModel();
    }

    public function makeModel()
    {
        return $this->setModel($this->model());
    }
    
    public function setModel($model)
    {
        $this->model = app()->make($model);

        return $this;
    }
    
    public function model()
    {
        return User::class;
    }
    
    public function all($columns = ['*'])
    {
        return $this->model->get($columns);
    }

    // other methods ...

    public function filters(array $filters)
    {
        $this->model = $this->eloquentBuilder->to($this->model(), $filters);

        return $this;
    }
}

filters 方法通过注入的 EloquentBuilder 将请求的过滤器应用于查询。

注入仓库

现在,我们可以在 UserController 的构造函数中简单地“类型提示”它

<?php

namespace App\Http\Controllers;

use App\Repositories\UserRepository;
use Illuminate\Http\Request;

class UserController extends Controller
{

    protected $users;

    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }

    public function index(Request $request)
    {
        return $this->users->filters($request->all())->get();
    }
}

测试

composer test

贡献

有关详细信息,请参阅CONTRIBUTING

安全

如果您发现任何与安全相关的问题,请通过电子邮件 fouladgar.dev@gmail.com 联系,而不是使用问题跟踪器。

许可协议

Eloquent-Builder 在 MIT 许可协议下发布。有关详细信息,请参阅附带的 LICENSE 文件。

用 ❤️ 为您打造。