基于Laravel编写的筛选项黑科技
目录:
FilterController.php
<?php
namespace Modules\Student\Http\Controllers;
use Illuminate\Routing\Controller;
use Mockery\Exception;
use Symfony\Component\Yaml\Yaml;
/**
* author:yolo
* 筛选黑科技,通过Filter/*.yaml文件获取筛选列表,
* 根据路由$request->all()参数,智能匹配指定模型的筛选函数
*
* example:
* 设置筛选文件 Filter/模型名_filter_config.yaml
*
* // 获取所有筛选项
* FilterController::setModule('Student', 'student'); //模块名, 模型名
* FilterController::getScopeFilters(); // 获取所有筛选项
*
* // 构建查询器,进行筛选
* FilterController::setModule('Student', 'student'); //模块名, 模型名
* $query = FilterController::QueryBulider($query, $request); // 构建查询器,进行筛选
*
* Class FilterController
* @package Modules\Student\Http\Controllers
*/
class FilterController extends Controller
{
private static $module;
private static $model;
public static function setModule($moduleName, $modelName)
{
if (null === static::$module) {
self::$module = $moduleName;
}
if (null === static::$model) {
self::$model = $modelName;
}
}
public static function getModule()
{
return static::$module . static::$model;
}
public static function getScopeFilters()
{
if (is_null($moduleName = static::$module)) {
throw new Exception('请使用setModule方法设置模块名称');
}
if (is_null($modelName = static::$model)) {
throw new Exception('请使用setModel方法设置模型名称');
}
// 获取当前模型对应的筛选项配置文件
if (file_exists($filterConfigPath = module_path(ucfirst($moduleName)) . '/' . 'Filters/' . strtolower($modelName) . '_filter_config.yaml')) {
try {
$filterContent = Yaml::parse(file_get_contents($filterConfigPath));
} catch (Exception $e) {
throw new Exception("{$filterConfigPath}文件格式不规范");
}
}
return self::dataTransfer($filterContent);
}
// 对options配置内容进行数据转换
private static function dataTransfer($data)
{
$transfer = function ($item) {
if (isset($item['options']) && is_string($item['options'])) {
if (isset($item['modelClass'])) {
$optionsMethod = $item['options'];
$item['options'] = (new $item['modelClass'])->$optionsMethod();
unset($item['modelClass']);
} else {
throw new Exception('请为options选择项指定模型');
}
}
return $item;
};
if (isset($data['scopes'])) {
$data['scopes'] = array_map($transfer, $data['scopes']);
}
return $data;
}
public static function QueryBulider($query, $request)
{
$filterContent = self::getScopeFilters();
// 对其进行遍历,获得所有的键,根据键判断是否存在,存在则执行筛选查询。
if (isset($filterContent['scopes'])) {
foreach ($filterContent['scopes'] as $key => $item) {
if (isset($request->$key)) {
if (isset($item['scope']) && !empty($scopeFunction = lcfirst($item['scope']))) {
$query = $query->$scopeFunction($request->$key);
} else {
$query = $query->where($key, $request->$key);
}
}
}
}
return $query;
}
}
student_filter_config.yaml
# ===================================
# Filter Scope Definitions
# ===================================
scopes:
education:
label: 最高学历
options:
本科: 本科
硕士: 硕士
博士: 博士
中专及以下: 中专及以下
scope: FilterEducation
age:
label: 年龄
modelClass: Modules\Student\Entities\Student
options: getAgeOptions
scope: FilterAge
Student.php<?php
namespace Modules\Student\Entities;
use Illuminate\Database\Eloquent\Model;
use Prettus\Repository\Contracts\Transformable;
use Prettus\Repository\Traits\TransformableTrait;
/**
* @SWG\Definition(
* definition="StudentList",
* type="object",
* allOf={
* @SWG\Schema(
* required={"id"},
* @SWG\Property(property="total", format="", type="integer",description="总数"),
* @SWG\Property(property="page", format="", type="integer",description="当前页"),
* @SWG\Property(property="limit", format="", type="integer",description="页大小"),
* @SWG\Property(
* property="data",
* format="",
* type="array",
* @SWG\Items(ref="#/definitions/Student")
* )
* )
* }
* )
*/
class Student extends Model implements Transformable
{
use TransformableTrait;
protected $guarded = ['id'];
protected $table = "students";
public function edus()
{
return $this->hasMany(StudentEdu::class);
}
public function jobs()
{
return $this->hasMany(StudentJob::class);
}
public function exams()
{
return $this->hasMany(StudentExam::class);
}
public function pays()
{
return $this->hasMany(StudentPay::class);
}
public function grant()
{
return $this->hasOne(StudentGrant::class);
}
public function scopeFilterEducation($query, $value)
{
return $query->where('education', $value);
}
public function getAgeOptions()
{
return [
"本科" => "本科",
"硕士" => "硕士",
"博士" => "博士",
"中专及以下" => "中专及以下",
];
}
}
composer.json需要插入 "symfony/yaml": "^4.0",