版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
前言:l5-repository是一个很强大的扩展,Laravel中必不可少.推荐一下笔者之前写过关于它的一些博客
(1)本章主要说明如何设置自己的 RequestCriteria类并支持between条件
(2)上述是修改源码,比较不建议
如果我们不想去修改源码内容,其实最好的做法是再另外写一个RequestCriteria类,在repository基类的boot方法中直接使用
$this->pushCriteria(app(RequestCriteria::class));
再献上自己的RequestCriteria类
- 上面的链接是l5-repository在github上的问题解决方案。笔者觉得我们应该善于利用开源项目的Issues和pull requests
<?php
namespace App\Criteria;
use Illuminate\Http\Request;
use Prettus\Repository\Contracts\CriteriaInterface;
use Prettus\Repository\Contracts\RepositoryInterface;
/**
* 此类基于\Prettus\Repository\Criteria\RequestCriteria修改
*/
class RequestCriteria implements CriteriaInterface
{
/**
* @var \Illuminate\Http\Request
*/
protected $request;
public function __construct(Request $request)
{
$this->request = $request;
}
/**
* Apply criteria in query repository
*
* @param Builder|Model $model
* @param RepositoryInterface $repository
*
* @return mixed
* @throws \Exception
*/
public function apply($model, RepositoryInterface $repository)
{
$fieldsSearchable = $repository->getFieldsSearchable();
$search = $this->request->get(config('repository.criteria.params.search', 'search'), null);
$searchFields = $this->request->get(config('repository.criteria.params.searchFields', 'searchFields'), null);
$filter = $this->request->get(config('repository.criteria.params.filter', 'filter'), null);
$orderBy = $this->request->get(config('repository.criteria.params.orderBy', 'orderBy'), null);
$sortedBy = $this->request->get(config('repository.criteria.params.sortedBy', 'sortedBy'), 'asc');
$with = $this->request->get(config('repository.criteria.params.with', 'with'), null);
$searchJoin = $this->request->get(config('repository.criteria.params.searchJoin', 'searchJoin'), null);
$sortedBy = !empty($sortedBy) ? $sortedBy : 'asc';
if ($search && is_array($fieldsSearchable) && count($fieldsSearchable)) {
$searchFields = is_array($searchFields) || is_null($searchFields) ? $searchFields : explode(';', $searchFields);
$fields = $this->parserFieldsSearch($fieldsSearchable, $searchFields);
$isFirstField = true;
$searchData = $this->parserSearchData($search);
$search = $this->parserSearchValue($search);
$modelForceAndWhere = strtolower($searchJoin) === 'and';
$model = $model->where(function ($query) use ($fields, $search, $searchData, $isFirstField, $modelForceAndWhere) {
/** @var Builder $query */
foreach ($fields as $field => $condition) {
if (is_numeric($field)) {
$field = $condition;
$condition = "=";
}
$value = null;
$condition = trim(strtolower($condition));
if (isset($searchData[$field])) {
// $value = ($condition == "like" || $condition == "ilike") ? "%{$searchData[$field]}%" : $searchData[$field];
switch ($condition) {
case 'like':
case 'ilike':
$value = "%{$searchData[$field]}%";
break;
case 'between':
$temp = $searchData[$field];
$temp = explode(',', $temp);
$value = $temp;
break;
case 'in':
$temp = $searchData[$field];
$temp = explode(',', $temp);
$value = $temp;
break;
default:
$value = $searchData[$field];
break;
}
} else {
if (!is_null($search)) {
$value = ($condition == "like" || $condition == "ilike") ? "%{$search}%" : $search;
}
}
$relation = null;
if(stripos($field, '.')) {
$explode = explode('.', $field);
$field = array_pop($explode);
$relation = implode('.', $explode);
}
$modelTableName = $query->getModel()->getTable();
if ( $isFirstField || $modelForceAndWhere ) {
if (!is_null($value)) {
if(!is_null($relation)) {
$query->whereHas($relation, function($query) use($field,$condition,$value) {
$query->where($field,$condition,$value);
});
} else {
// $query->where($modelTableName.'.'.$field,$condition,$value);
switch ($condition) {
case 'between':
$query->whereBetween($modelTableName.'.'.$field, $value);
break;
case 'in':
$query->whereIn($modelTableName.'.'.$field, $value);
break;
default:
$query->where($modelTableName.'.'.$field,$condition,$value);
break;
}
}
$isFirstField = false;
}
} else {
if (!is_null($value)) {
if(!is_null($relation)) {
$query->orWhereHas($relation, function($query) use($field,$condition,$value) {
$query->where($field,$condition,$value);
});
} else {
$query->orWhere($modelTableName.'.'.$field, $condition, $value);
}
}
}
}
});
}
if (isset($orderBy) && !empty($orderBy)) {
$split = explode('|', $orderBy);
if(count($split) > 1) {
/*
* ex.
* products|description -> join products on current_table.product_id = products.id order by description
*
* products:custom_id|products.description -> join products on current_table.custom_id = products.id order
* by products.description (in case both tables have same column name)
*/
$table = $model->getModel()->getTable();
$sortTable = $split[0];
$sortColumn = $split[1];
$split = explode(':', $sortTable);
if(count($split) > 1) {
$sortTable = $split[0];
$keyName = $table.'.'.$split[1];
} else {
/*
* If you do not define which column to use as a joining column on current table, it will
* use a singular of a join table appended with _id
*
* ex.
* products -> product_id
*/
$prefix = str_singular($sortTable);
$keyName = $table.'.'.$prefix.'_id';
}
$model = $model
->leftJoin($sortTable, $keyName, '=', $sortTable.'.id')
->orderBy($sortColumn, $sortedBy)
->addSelect($table.'.*');
} else {
$model = $model->orderBy($orderBy, $sortedBy);
}
}
if (isset($filter) && !empty($filter)) {
if (is_string($filter)) {
$filter = explode(';', $filter);
}
$model = $model->select($filter);
}
if ($with) {
$with = explode(';', $with);
$model = $model->with($with);
}
return $model;
}
/**
* @param $search
*
* @return array
*/
protected function parserSearchData($search)
{
$searchData = [];
if (stripos($search, ':')) {
$fields = explode(';', $search);
foreach ($fields as $row) {
try {
list($field, $value) = explode(':', $row);
$searchData[$field] = $value;
} catch (\Exception $e) {
//Surround offset error
}
}
}
return $searchData;
}
/**
* @param $search
*
* @return null
*/
protected function parserSearchValue($search)
{
if (stripos($search, ';') || stripos($search, ':')) {
$values = explode(';', $search);
foreach ($values as $value) {
$s = explode(':', $value);
if (count($s) == 1) {
return $s[0];
}
}
return null;
}
return $search;
}
protected function parserFieldsSearch(array $fields = [], array $searchFields = null)
{
if (!is_null($searchFields) && count($searchFields)) {
$acceptedConditions = config('repository.criteria.acceptedConditions', [
'=',
'like'
]);
$originalFields = $fields;
$fields = [];
foreach ($searchFields as $index => $field) {
$field_parts = explode(':', $field);
$temporaryIndex = array_search($field_parts[0], $originalFields);
if (count($field_parts) == 2) {
if (in_array($field_parts[1], $acceptedConditions)) {
unset($originalFields[$temporaryIndex]);
$field = $field_parts[0];
$condition = $field_parts[1];
$originalFields[$field] = $condition;
$searchFields[$index] = $field;
}
}
}
foreach ($originalFields as $field => $condition) {
if (is_numeric($field)) {
$field = $condition;
$condition = "=";
}
if (in_array($field, $searchFields)) {
$fields[$field] = $condition;
}
}
if (count($fields) == 0) {
throw new \Exception(trans('repository::criteria.fields_not_accepted', ['field' => implode(',', $searchFields)]));
}
}
return $fields;
}
}