使用 RequestCriteria 统一搜索功能,可自动根据 url 按字段进行搜索,无需写方法
1. 后台搜索框的基本代码:
要求表单中的 name 与数据表中的字段名完全一致。
注意:这里是 button,而不是 submit
2. 在YourModelRepositoryEloquent.php (如FlashRepositoryEloquent.php) 中添加 $fieldSearchable 字段
如:
protected $fieldSearchable = [
'id',
'snap_goods_name' => 'like',
'username',
'order_status',
'created_at' => ">=",
'created_at@' => "<=",
'source_id',
'paymentInfo.payment_type'
];
注意:
- 要列出所有需要进行搜索的字段。
- 等于的可以省略,
- 模糊搜索用 like,
- 范围搜索也直接写。
- 如果一个字段需要用一次以上,需要对 key 进行重写,加一个@
其中,最后一个功能是在 BaseRepositoryEloquent 中定义的。
默认的键值间的分隔符为:, 如http://prettus.local/users?search=name:John Doe;email:[email protected]
可以进行自定义。
在 BaseRepositoryEloquent.php 的构造方法中,
$this->keyValueSeparator = '|:'
。
组件中默认不包含范围选择符,即sql中的between用法。我们进行了改写,以支持该用法。
BaseRepositoryEloquent 中,添加解析搜索url的方法。
public function parserSearchData($searchData)
{
if (!empty($searchData) && is_array($searchData)) {
foreach ($searchData as $index => $item) {
$method = sprintf("parser%s4Search", ucfirst(camel_case(str_replace('@', '', $index))));
$model = $this->getModel();
if (method_exists($model, $method)) {
$searchData[$index] = $model->{$method}($item);
}
}
}
return $searchData;
}
以及解析原始搜索数据的方法
public function parserOriginSearchData($search)
{
$searchData = [];
if (stripos($search, $this->keyValueSeparator)) {
$fields = explode($this->paramSeparator, $search);
foreach ($fields as $row) {
try {
list($field, $value) = explode($this->keyValueSeparator, $row);
$searchData[trim($field)] = trim($value);
} catch (\Exception $e) {
//Surround offset error
}
}
}
return $searchData;
}
业务需要,添加了整合后的获取搜索参数的方法
public function getSearchData($param = null, $is_origin = true)
{
$search = $this->request->get(config('repository.criteria.params.search', 'search'), null);
$searchData = $this->parserOriginSearchData($search);
if (false == $is_origin) {
$searchData = $this->parserSearchData($searchData);
}
if (!empty($param)) {
if (isset($searchData[$param])) {
$searchData = $searchData[$param];
} else {
$searchData = null;
}
}
return $searchData;
}
3. js 文件中添加解析url的方法。
// 搜索 按钮
searchWithParams('/magazine/order?page=1');
function searchWithParams(url) {
$("#btn_search").click(function () {
var params = {};
$("#frm_search_info select, #frm_search_info input[type=text], #frm_search_info input[type=hidden]").each(function () {
var value = $(this).val();
if ('' != value) {
params[$(this).attr('name')] = value;
}
});
if (!$.isEmptyObject(params)) {
url += "&search=" + parserParams2Url(params);
}
location.href = url;
});
}
该方法实现了对所有输入框、下拉框等搜索框内容的收集并处理,生成一个 Repository 可解析的 url。
4. 回显的数据不需要通过控制器获取后回传,在模板中通过 $searchCondition 全局变量获取即可
如何使用?
控制器中的方法会非常简洁:
public function getIndex(Request $request)
{
$flashes = $this->repositoryInterface->paginate();
return View::make("flash/index", array(
"flashes" => $flashes,
"flashTypes" => Flash::$flashTypes,
));
}
第二部分
上述搜索方法只是实现了单表搜索,如果搜索涉及到跨表该怎么处理?
场景:在模型Order的列表页进行搜索,但搜索的关键字是模型Payment的一个字段,模型Payment有一个指向模型Order的外键 order_id。
实现:
1. 在 app/Models/Order 中,建立与 Payment 模型的关联关系。
/**
* 支付信息关联关系
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function paymentInfo()
{
return $this->hasOne('App\Models\Payment', 'order_id', 'id');
}
2. Order 的模板文件(列表 resources/views/backend/order/index.blade.php)中,搜索相关部分的 name 和字段名都要加上关联关系的方法前缀。
3. 在YourModelRepositoryEloquent.php (如FlashRepositoryEloquent.php) 中添加 $fieldSearchable 字段
如:
protected $fieldSearchable = [
'paymentInfo.payment_type'
];
要与模板文件的name一致。