[√新技能] 搜索器——統一管理你的搜索代碼
模型搜索器是自模型獲取器和修改器功能之后的第三個統一管理的利器,主要用于封裝字段(或者搜索標識)的查詢條件表達式,一個搜索器對應一個特殊的方法(該方法必須是public類型),方法命名規范為:searchFieldNameAttr(FieldName為數據表字段的駝峰轉換),搜索器僅在調用withSearch方法的時候觸發。
搜索器的使用場景包括:
????·限制和規范表單的搜索條件;
立即學習“PHP免費學習筆記(深入)”;
????·預定義查詢條件簡化查詢。
例如,我們需要給User模型定義name字段和時間字段的搜索器,可以使用:
<?php namespace appindexmodel; use thinkModel; class User extends Model { public function searchNameAttr($query, $value, $data) { $query->where('name','like',?$value?.?'%'); ????} ???? ????public?function?searchCreateTimeAttr($query,?$value,?$data) ????{ ????????$query->whereBetweenTime('create_time',?$value[0],?$value[1]); ????}???? }
搜索器方法的參數有三個,第一個是查詢對象,第二個是當前搜索標識的值,第三個是當前所有的搜索數據(可選)。
然后,我們可以使用下面的查詢
User::withSearch(['name',?'create_time'],?[ 'name'=>'think', ????'create_time'=>['2018-8-1','2018-8-5'], ????????'status'=>1 ????]) ->select();
最終生成的SQL語句類似于
SELECT?*?FROM?`think_user`?WHERE??`name`?LIKE?'think%'?AND?`create_time`?BETWEEN?'2018-08-01?00:00:00'?AND? '2018-08-05?00:00:00'
可以看到查詢條件中并沒有status字段的數據,因此可以很好的避免表單的非法查詢條件傳入,在這個示例中僅能使用name和create_time條件進行查詢。
事實上,除了在搜索器中使用查詢表達式外,還可以使用其它的任何查詢構造器以及鏈式操作。
例如,你需要通過表單定義的排序字段進行搜索結果的排序,可以使用
<?php namespace appindexmodel; use thinkModel; class User extends Model { public function searchNameAttr($query, $value, $data) { $query->where('name','like',?$value?.?'%'); ????????if?(isset($data['sort']))?{ ????????$query->order($data['sort']); ????????}???????? ????} ???? ????public?function?searchCreateTimeAttr($query,?$value,?$data) ????{ ????????$query->whereBetweenTime('create_time',?$value[0],?$value[1]); ????}?????? }
然后,我們可以使用下面的查詢
User::withSearch(['name','create_time',?'status'],?[ 'name'=>'think', ????'create_time'=>['2018-8-1','2018-8-5'], ????????'status'=>1, ????????'sort'=>['status'=>'desc'], ????]) ->select();
最終查詢的SQL可能是
SELECT?*?FROM?`think_user`?WHERE??`name`?LIKE?'think%'?AND?`create_time`?BETWEEN?'2018-08-01?00:00:00'?AND? '2018-08-05?00:00:00'?ORDER?BY?`status`?DESC
你還可以給搜索器定義字段別名,例如:
User::withSearch(['name'?=>?'nickname','create_time',?'status'],?[ 'nickname'=>'think', ????'create_time'=>['2018-8-1','2018-8-5'], ????????'status'=>1, ????????'sort'=>['status'=>'desc'], ????]) ->select();
搜索的數據使用的是nickname字段標識,但我們仍然使用的是name字段標識的搜索器(也就是searchNameAttr方法)。
搜索器通常會和查詢范圍進行比較,搜索器無論定義了多少,只需要一次調用,查詢范圍如果需要組合查詢的時候就需要多次調用。
如果你使用的是Db查詢方法,仍然可以使用搜索器功能,只是搜索器方法定義需要改成閉包方式,如下:
User::withSearch(['name'?=>?function($query,$value,$data){ ????$query->where('name','like',?$value?.?'%'); },?'create_time'=>function($query,$value,$data){ ????$query->whereBetweenTime('create_time',?$value[0],?$value[1]); }],?[ 'name'=>'think', ????'create_time'=>['2018-8-1','2018-8-5'], ????????'status'=>1 ????]) ->select();
PHP中文網,有大量免費的ThinkPHP入門教程,歡迎大家學習!
本文轉自:https://blog.thinkphp.cn/783775