erp/app/Filters/Filters.php

122 lines
3.6 KiB
PHP
Raw Permalink Normal View History

2022-07-28 13:46:08 +08:00
<?php
namespace App\Filters;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Support\Arr;
class Filters
{
/**
* @var Request
*/
protected $request;
/**
* The Eloquent builder.
*
* @var \Illuminate\Database\Eloquent\Builder
*/
protected $builder;
/**
* Registered filters to operate upon.
*
* @var array
*/
protected $filters = [];
/**
* Create a new ThreadFilters instance.
*
* @param Request $request
*/
public function __construct()
{
$this->request = Request();
}
/**
* Apply the filters.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @return \Illuminate\Database\Eloquent\Builder
*/
public function apply($builder)
{
$this->builder = $builder;
$fieldsSearchable = $this->getFieldsSearchable();
$fields = $this->getFilters($fieldsSearchable);
if (is_array($fields) && count($fields) && is_array($fieldsSearchable) && count($fieldsSearchable)) {
foreach ($fields as $field => $value) {
$method = Str::camel($field);
if (method_exists($this, $method)) {
$this->$method($value);
} elseif (isset($fieldsSearchable[$field])) {
$condition = $fieldsSearchable[$field];
$value = $condition == "like" ? "%{$value}%" : $value;
$relation = null;
if (stripos($field, '.')) {
$explode = explode('.', $field);
$field = array_pop($explode);
$relation = implode('.', $explode);
}
$modelTableName = $builder->getModel()->getTable();
$field = Str::snake($field);
if (!is_null($value)) {
if (!is_null($relation)) {
$builder->whereHas($relation, function ($query) use ($field, $condition, $value) {
$query->where($field, $condition, $value);
});
} else {
$builder->where($modelTableName . '.' . $field, $condition, $value);
}
}
}
}
return $this->builder;
}
}
/**
* Fetch all relevant filters from the request.
*
* @return array
*/
public function getFilters($fieldsSearchable)
{
if (!is_array($fieldsSearchable) || count($fieldsSearchable) == 0) {
return [];
}
$keys = array_keys($fieldsSearchable);
//$this->request->only() 会把user.nickname参数里包含"." 转换成数组
//Arr::dot 方法使用「.」号将将多维数组转化为一维数组:
return array_filter(Arr::dot($this->request->only($keys)), function ($value) {
return !is_null($value) && $value != '';
});
}
//获取model 可以查询的参数
protected function getFieldsSearchable()
{
$model = $this->builder->getModel();
if (!property_exists($model, 'fieldSearchable')) {
return [];
}
$fieldSearchable = $model->fieldSearchable;
$fields = [];
foreach ($fieldSearchable as $field => $condition) {
if (is_numeric($field)) {
$field = $condition;
$condition = "=";
}
$fields[$field] = $condition;
}
return $fields;
}
}