shureban/laravel-searcher

Laravel SDK,用于通过请求在数据库中搜索数据

安装次数: 2,198

依赖项: 0

建议者: 0

安全性: 0

星标: 2

关注者: 1

分支: 0

开放问题: 0

类型:laravel-package

2.4.1 2023-11-09 16:16 UTC

This package is auto-updated.

Last update: 2024-09-09 18:23:40 UTC


README

安装

使用以下命令通过composer安装此包:

composer require shureban/laravel-searcher

将以下类添加到 config/app.php 文件中的 providers 数组中:

Shureban\LaravelSearcher\SearcherServiceProvider::class,

您也可以发布配置文件以更改实现(例如,将接口更改为特定类)。

php artisan vendor:publish --provider="Shureban\LaravelSearcher\SearcherServiceProvider"

如何使用

默认情况下,将您的搜索器放在 app\Http\Searchers 文件夹中。

所有搜索器变体的示例。

getQuery 方法

应返回应用过滤器的查询。您可以修改此查询 Model::query()->with(['relation_1', 'relation_2' => fn() => ...])

getFilters 方法

应返回关联数组,其中

  • 键必须等于您的请求参数
  • 值必须是与 \Shureban\LaravelSearcher\Searcher 相关的对象

示例

在这种情况下

  • 'age' - 是请求参数 age
  • 'client_age' - 是数据库列名
  • new Between(...) - 过滤规则
return ['age' => new Between('client_age')];
class YourFirstSearcher extends Searcher
{
    /**
     * @return Builder
     */
    protected function getQuery(): Builder
    {
        return Model::query();
    }

    /**
     * @return ColumnFilter[]
     */
    protected function getFilters(): array
    {
        return [
          //| Request param name | Filter object               | Expected value type
          //-------------------------------------------------------------------------
            // Simple cases
            'is_single'        => new Boolean('is_single'),     // bool
            'age'              => new Between('client_age'),    // array (2 elements)
            'salary'           => new BetweenRange('salary'),   // array (2 elements)
            'birthday'         => new BetweenDates('birthday'), // array (2 elements)
            'id'               => new Equal('id'),              // any
            'created_at'       => new EqualDate('created_at'),  // date
            'height'           => new Gt('height'),             // number
            'max_height'       => new Gte('max_height'),        // number
            'updated_at'       => new GtDate('updated_at'),     // date
            'deleted_at'       => new GteDate('deleted_at'),    // date
            'statuses'         => new In('status'),             // array
            'image_id'         => new IsNull('image_id'),       // bool
            'email'            => new Like('email'),            // mixed
            'foot_size'        => new Lt('foot_size'),          // number
            'max_foot_size'    => new Lte('max_foot_size'),     // number
            'birthday'         => new LtDate('birthday'),       // date
            'hired_at'         => new LteDate('hired_at'),      // date
            'partner_statuses' => new NotIn('partner_status'),  // array
            'only_every_even'  => new Callback(
                fn(Builder $query, mixed $value) => $query->whereRaw('(id % 2 = 0)')
            ),                                                  // mixed


            // Modifier used. That case means, all rows where manager_id is equal to same value or null
            'manager_id' => new OrNull(new Like('manager_id')),
            'full_name'  => new OrEmpty(new Like('full_name')),
            'owner_id'   => new MultipleOr(new Equal('user_id'), new Like('manager_id'), new Relation('brokers', new Equal('id'))),
            // Working with relation modifiers
            'invoice_payouts'          => new Relation('invoices', new Between('amount')),
            'invoice_statuses'         => new Relation('invoices', new In('status')),
            'invoice_payment_method'   => new Relation('invoices', new Like('payment_method')),
            'invoice_process_statuses' => new Relation('invoices', new NotIn('process_status')),
        ];
    }
}

如何更改排序

要更改默认排序列,应覆盖方法 sortColumn

protected function sortColumn(): ?string
{
    return $this->request->get('sort_column', 'created_at');
}

如果您需要更改与某些列相关的排序行为,请这样做。覆盖方法 applySortBy

protected function applySortBy(Builder $query, string $sortColumn, SortType $sortType): Builder
{
    return match ($sortColumn) {
        'your_special_column'   => $query->orderBy('column_1', $sortType)->orderBy('column_2', $sortType),
        default                 => parent::applySortBy($query, $sortColumn, $sortType),
    };
}

真实案例

您的第一个搜索器

namespace App\Http\Searchers;

use Illuminate\Database\Eloquent\Builder;
use Shureban\LaravelSearcher\Filters\Like;
use Shureban\LaravelSearcher\Searcher;

class YourFirstSearcher extends Searcher
{
    /**
     * @return Builder
     */
    protected function getQuery(): Builder
    {
        return Model::query();
    }

    /**
     * @return ColumnFilter[]
     */
    protected function getFilters(): array
    {
        return [
            'id' => new Like('id'),
        ];
    }
}

请求

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rules\Enum;
use Illuminate\Validation\Rules\In;
use Shureban\LaravelSearcher\Enums\SortType;

class YourRequest extends FormRequest
{
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules(): array
    {
        return [
            'id'            => ['int', 'min:1', 'max:2000000000'],
            'sort_column'   => [new In(['id'])],
            'sort_type'     => [new Enum(SortType::class)],
        ];
    }
}

控制器

namespace App\Http\Controllers;

use Illuminate\Routing\Controller as BaseController;
use App\Http\Requests\YourFirstSearcher;

class YourController extends BaseController
{
    /**
     * @param YourRequest $request
     *
     * @return JsonResponse
     */
    public function __invoke(YourRequest $request): JsonResponse
    {
        $searcher  = new YourFirstSearcher($request);
        // Collection with all models without pagination and slicing by per_page
        $allModels = $searcher->all();
        // Collection contains per_page number of models and with page offset 
        $models    = $searcher->get();
        // Base Laravel LengthAwarePaginator
        $paginator = $searcher->paginate();

        return new JsonResponse($paginator);
    }
}