see http://www.trirand.com/jqgridwiki/doku.php?id=wiki:retrieving_data
本文給出jqgrid和laravel的Eloquent 數據交互接口。
1. json訪問格式
通過http://localhost:8000/json去獲取數據,在請求的時候,還會加上一些默認參數。
http://localhost:8000/json?_search=false&nd=1422412397217&rows=10&page=1&sidx=id&sord=desc
這個是真正在訪問的時候請求數據參數。
function pageInit() { var lastsel; jQuery("#list4").jqGrid({ width:"800", url: 'http://localhost:8000/json', datatype: "json", colNames: ['Inv No', 'game_name', 'game_id', 'game_server', 'game_auth', 'created_at', 'updated_at'], colModel: [ {name: 'id', index: 'id', width: 55}, {name: 'game_name', index: 'game_name', width: 90, editable: true}, {name: 'game_id', index: 'game_id', width: 100, editable: true}, {name: 'game_server', index: 'game_server', width: 80, align: "right", editable: true}, {name: 'game_auth', index: 'game_auth', width: 80, align: "right", editable: true}, {name: 'created_at', index: 'created_at', width: 200, align: "right", editable: true}, {name: 'updated_at', index: 'updated_at', width: 150, sortable: false, editable: true} ], rowNum: 10, rowList: [10, 20, 30], pager: '#pager2', sortname: 'id', viewrecords: true, sortorder: "desc", onSelectRow: function (id) { if (id && id !== lastsel) { // alert("hello"); jQuery('#list4').jqGrid('restoreRow', lastsel); jQuery('#list4').jqGrid('editRow', id, true); lastsel = id; } }, editurl: "http://www.trirand.com/blog/jqgrid/server.php", caption: "Using events example" }); jQuery("#list4").jqGrid('navGrid', "#pager2", {edit: false, add: false, del: false}); } </script>
服務器端代碼:
public function json() { $all = ModelAccount::all(); // $total = $all->count() / Input::get("rows"); $total = ceil($all->count()/Input::get("rows"));//*Input::get("rows") / 10; return '{"page":"'.Input::get("page").'","total":"'.$total.'","records":"'.$all->count().'","rows":'.$all.'}'; //return $all; }
這是一種最原始的方式。出來的界面如下圖
1.1 排序
感覺jqgrid是不會自己排序的,每次點擊排序的話,會發送請求給服務器端,服務器端會再執行一次數據庫查詢。這點感覺效率不是很高。
通過點擊Inv No上下排序的話,會再次發送一個請求。
http://localhost:8000/json?_search=false&nd=1422416288639&rows=10&page=1&sidx=id&sord=asc
如果點擊game_name的話,請求又變成了
http://localhost:8000/json?_search=false&nd=1422416317800&rows=10&page=1&sidx=game_name&sord=asc
根據分析,sord是決定排序是倒序還是順序。sidx是決定根據哪個字段來進行排序。
那么服務器端需要根據該請求做相應的判斷。
public function json() { $all = ModelAccount::orderBy(Input::get("sidx"), Input::get("sort"))->get(); $total = ceil($all->count()/Input::get("rows"));//*Input::get("rows") / 10; return '{"page":"'.Input::get("page").'","total":"'.$total.'","records":"'.$all->count().'","rows":'.$all.'}'; //return $all; }
1.2 優化查詢效率
我們看到每次查詢的時候時候都會把數據庫的表全部遍歷一遍,從效率優化的角度,應該每次只返回相應數量的數據就可以了。
按照上例,每次只需要取10條數據就可以了。
服務器端相應代碼修改如下:
public function json() { $value = ModelAccount::orderBy(Input::get("sidx"), Input::get("sort"))->take(Input::get("rows"))->get(); $all = ModelAccount::all()->count(); $total = ceil($all/Input::get("rows"));//*Input::get("rows") / 10; return '{"page":"'.Input::get("page").'","total":"'.$total.'","records":"'.$all.'","rows":'.$value.'}'; //return $all; }
通過chrome分析可以得到,確實每次只拉出來10條數據。
1.3 從哪里開始?
解決了數量問題,那么需要解決數據從哪里開始的問題了。
我們來看,如果用戶切換到第二個頁面的話,那么相應的請求就變成
http://localhost:8000/json?_search=false&nd=1422417279445&rows=10&page=2&sidx=id&sord=desc
服務器端的代碼相應需要修改
public function json() { $offset = (Input::get("page") - 1) * Input::get("rows"); $value = ModelAccount::orderBy(Input::get("sidx"), Input::get("sort"))->take(Input::get("rows"))->offset($offset)->get();//->paginate(Input::get("rows"))->getFrom($offset);//take(20)->offset(10)->get(); $all = ModelAccount::all()->count(); $total = ceil($all/Input::get("rows"));//*Input::get("rows") / 10; return '{"page":"'.Input::get("page").'","total":"'.$total.'","records":"'.$all.'","rows":'.$value.'}'; }
1.4 每次查詢的數據量
每次查詢的數據量是根據界面數據給出來的,在代碼中可以通過rowList來指定幾種。
1.5 條件查詢
通過點擊搜索,可以彈出搜索對話框。
點擊Find之后,會向服務器發送請求。
主要是4個參數
1._search=true
2.searchField=id
3.searchString=868
4.searchOper=eq
那么我們相應的服務器端代碼修改
public function json() { $searchField=''; $searchOper=''; $searchString=''; $value=''; $all=''; $offset = (Input::get("page") - 1) * Input::get("rows"); if(!strcmp(Input::get("_search"), "true")){ $searchField=Input::get("searchField"); $searchOper=Input::get("searchOper"); if(!strcmp($searchOper, "eq")) {//equal $searchOper="="; } else if(!strcmp($searchOper,"ne")) { //not equal $searchOper=""; } else if(!strcmp($searchOper,"bw")) { //begin with } else if(!strcmp($searchOper,"bn")) { //not begin with } else if(!strcmp($searchOper,"ew")) { //ends with } else if(!strcmp($searchOper,"en")) { //not ends with } else if(!strcmp($searchOper,"cn")) { //contains } else if(!strcmp($searchOper,"nc")) { //not contains } else if(!strcmp($searchOper,"nu")) { //is null } else if(!strcmp($searchOper,"nn")) { //not is null } else if(!strcmp($searchOper,"in")) { //is null } else if(!strcmp($searchOper,"ni")) { //is null } $searchString=Input::get("searchString"); $value = ModelAccount::where($searchField, $searchOper, $searchString)->orderBy(Input::get("sidx"), Input::get("sort"))->take(Input::get("rows"))->offset($offset)->get();//->paginate(Input::get("rows"))->getFrom($offset);//take(20)->offset(10)->get(); $all = ModelAccount::where($searchField, $searchOper, $searchString)->count(); } else { $value = ModelAccount::orderBy(Input::get("sidx"), Input::get("sort"))->take(Input::get("rows"))->offset($offset)->get();//->paginate(Input::get("rows"))->getFrom($offset);//take(20)->offset(10)->get(); $all = ModelAccount::all()->count(); } $total = ceil($all/Input::get("rows"));//*Input::get("rows") / 10; return '{"page":"'.Input::get("page").'","total":"'.$total.'","records":"'.$all.'","rows":'.$value.'}'; }
如何去除多余的搜索條件?
修改對應語言文件的search段中odata.
odata: [{ oper:'eq', text:'等於\u3000\u3000'},{ oper:'ne', text:'不等\u3000\u3000'},{ oper:'lt', text:'小於\u3000\u3000'},{ oper:'le', text:'小於等於'},{ oper:'gt', text:'大於\u3000\u3000'},{ oper:'ge', text:'大於等於'},{ oper:'bw', text:'開始於'},{ oper:'bn', text:'不開始於'},{ oper:'in', text:'屬於\u3000\u3000'},{ oper:'ni', text:'不屬於'},{ oper:'ew', text:'結束於'},{ oper:'en', text:'不結束於'},{ oper:'cn', text:'包含\u3000\u3000'},{ oper:'nc', text:'不包含'},{ oper:'nu', text:'不存在'},{ oper:'nn', text:'存在'}],
2.數據修改
2.1 通過事件實現
雙擊某一行之后,可以進行修改
2.2 導航條編輯
通過添加
jQuery("#list4").jqGrid('inlineNav',"#pager2");
會使用內部編輯。
2.3 數據提交
編輯了數據,那么我們怎么提交到數據庫呢?
首先需要我們在laravel里面添加一條post路由。
Route::post('edit_jqgrid', array('as' => 'edit_jqgrid', 'uses' => 'ControllerAccount@edit_jqgrid'));
在jqgrid的javascript里面添加:
editurl: http://localhost:8000/edit_jqgrid,
在編輯保存的時候,通過chrome分析確實是發送了edit_jqgrid的post請求。
2.4 前端界面
jQuery('#list4').jqGrid('navGrid', '#pager2', { edit: true, add : true, del : true, search :true, searchtext: "查找", addtext: "添加", edittext: "編輯", deltext: "刪除", refreshtext:"刷新" } , { closeOnEscape: true,//Closes the popup on pressing escape key reloadAfterSubmit :true, drag :true, afterSubmit :function (response, postdata) { if (response.responseText == "") { $(this).jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid');//Reloads the grid after edit return [true, ""]; } else { $(this).jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid'); //Reloads the grid after edit return [false, response.responseText];//Captures and displays the response text on th Edit window } }, editData: { id: function () { var sel_id = $('#list4').jqGrid('getGridParam', 'selrow') ; var value = $('#list4').jqGrid('getCell',sel_id, 'id'); return value; } } } , { closeAfterAdd: true,//Closes the add window after add afterSubmit:function (response, postdata) { if (response.responseText == "") { $(this).jqGrid('setGridParam',{ datatype: 'json' }).trigger('reloadGrid');//Reloads the grid after Add return [true, '']; } else { $(this).jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid')//Reloads the grid after Add return [false, response.responseText]; } } }, { //DELETE closeOnEscape: true, closeAfterDelete :true, reloadAfterSubmit : true, drag:true, afterSubmit:function (response, postdata) { if (response.responseText == "") { $("#list4").trigger("reloadGrid", [{current: true}]) ; return [false, response.responseText]; } else { $(this).jqGrid('setGridParam', { datatype: 'json' }).trigger('reloadGrid'); return [true, response.responseText]; } } , delData: { EmpId: function () { var sel_id = $('#list4').jqGrid('getGridParam', 'selrow'); var value = $('#list4').jqGrid('getCell',sel_id, 'id'); return value; } } }, {//SEARCH closeOnEscape: true } ) ;
2.5 添加數據
通過chrome分析,可以看到里面有個oper為edit
2.6 修改數據
通過chrome分析,可以看到里面有個oper為add
2.7 刪除數據
通過chrome分析,可以看到里面有個oper為del
3.界面本地化
現有模塊的本地化,可以使用以下語句
<script src="js/i18n/grid.locale-cn.js" type="text/javascript"></script>
其他文字的本地化,在這里面需要注意一點,盡量使用統一的本地化模式,因為本來laravel里面會有一個本地化的模塊。
3.1 laravel 本地化
在app/lang里面增加一個cn目錄,新建一個message.php文件,內容如下:
<?php /** * Created by PhpStorm. * User: Administrator * Date: 2015/1/30 * Time: 11:11 */ return array( 'welcome' => 'Welcome to our application', 'id' => '編號', 'game_name' => '玩家名字', 'game_id' => '玩家編號', 'game_server' => '游戲區', 'game_auth' => '權限', 'created_at' => '創建時間', 'updated_at' => '更新時間' );
修改config/app.php文件,將locale設置為cn.
修改jqgrid代碼:
datatype: "json", colNames: ['{{Lang::get('message.id')}}', '{{Lang::get('message.game_name')}}', '{{Lang::get('message.game_id')}}', '{{Lang::get('message.game_server')}}', '{{Lang::get('message.game_auth')}}', '{{Lang::get('message.created_at')}}', '{{Lang::get('message.updated_at')}}'], colModel: [
修改完成之后顯示界面如下:
4.界面自定義
4.1 字體
這個字體個人覺得比較難看,我想改成微軟雅黑字體,並且字體大小增加一倍。
<STYLE type="text/css"> /* Jqgrid */ .ui-jqgrid .ui-jqgrid-view {font-size:14px;} /*修改grid標題的字體大小*/ .ui-jqgrid-sortable {font-size:14px;} /*修改列名的字體大小*/ .ui-widget-content .jqgrow .ui-row-ltr .ui-jqgrid-view {font-size:14px;} /*修改表格內容字體,不起作用*/ </style>
這個時候只是修改表格里面的字體大小,其他的大小還沒有修改。
添加:
<STYLE type="text/css"> /* Jqgrid */ .ui-jqgrid .ui-jqgrid-view {font-size:14px;} /*修改grid標題的字體大小*/ .ui-jqgrid .ui-jqgrid-pager {font-size:14px;} /*修改grid標題的字體大小*/ .ui-jqgrid-sortable {font-size:14px;} /*修改列名的字體大小*/ .ui-widget-content .jqgrow .ui-row-ltr .ui-jqgrid-view {font-size:14px;} /*修改表格內容字體,不起作用*/ </style>
添加:
<STYLE type="text/css"> /* Jqgrid */ .ui-jqgrid .ui-jqgrid-view {font-size:14px;} /*修改grid標題的字體大小*/ .ui-jqgrid .ui-jqgrid-pager {font-size:14px;} /*修改grid標題的字體大小*/ .ui-jqgrid .ui-jqgrid-titlebar {font-size: 16px;} .ui-jqgrid-sortable {font-size:14px;} /*修改列名的字體大小*/ .ui-widget-content .jqgrow .ui-row-ltr .ui-jqgrid-view {font-size:14px;} /*修改表格內容字體,不起作用*/ </style>
最后的css代碼為:
<STYLE type="text/css"> /* Jqgrid */ .ui-jqgrid .ui-jqgrid-view {font-size:14px;} /*修改grid標題的字體大小*/ .ui-jqgrid .ui-jqgrid-pager {font-size:14px;} /*修改grid標題的字體大小*/ .ui-jqgrid .ui-jqgrid-titlebar {font-size: 16px;} .ui-jqdialog-title {font-size: 14px;} .ui-jqgrid-sortable {font-size:14px;} /*修改列名的字體大小*/ .ui-widget-content .jqgrow .ui-row-ltr .ui-jqgrid-view {font-size:14px;} /*修改表格內容字體,不起作用*/ .CaptionTD {font-size:14px} .fm-button {font-size:14px} .ui-jqdialog {font-size: 14px} </style>
4.2 搜索
4.2.1組合搜索
在navGrid的搜索參數里面增加
{//SEARCH closeOnEscape: true, multipleSearch:true, //multipleGroup:true }
翻譯成正常的url地址為:
根據分析組合查詢分為大致的4種情況:
1.同時滿足一個條件
2.同時滿足n個條件
3.滿足任一一個條件
4.滿足任一n個條件
根據以上分析,服務器端相應的代碼修改為
public function json() { $searchField=''; $searchOper=''; $searchString=''; $value=''; $all=''; $filters=''; $offset = (Input::get("page") - 1) * Input::get("rows"); $filters = Input::get("filters"); if($filters) { $json_data = json_decode($filters); $groupOp = $json_data->groupOp; $rules = $json_data->rules; //return $rules; $r=''; $number=0; foreach($rules as $rule) { $rule->op = "="; if($number == 0) { $r = $r . ' ' . $rule->field . ' ' . $rule->op . ' ' . $rule->data;//.'"'; } else { if(!strcmp($groupOp, "AND")) { $r = $r . ' and ' . $rule->field . ' ' . $rule->op . ' ' . $rule->data;//.'"'; } else { $r = $r . ' or ' . $rule->field . ' ' . $rule->op . ' ' . $rule->data;//.'"'; } } $number = $number+1; } //$r=$r.' " '; //$r='id = 901 or game_server = 888'; $value = ModelAccount::whereRaw($r)->orderBy(Input::get("sidx"), Input::get("sort"))->take(Input::get("rows"))->offset($offset)->get();//->paginate(Input::get("rows"))->getFrom($offset);//take(20)->offset(10)->get(); $all = ModelAccount::whereRaw($r)->count(); } else { if (!strcmp(Input::get("_search"), "true")) { $searchField = Input::get("searchField"); $searchOper = Input::get("searchOper"); if (!strcmp($searchOper, "eq")) {//equal $searchOper = "="; } else if (!strcmp($searchOper, "ne")) { //not equal $searchOper = ""; } else if (!strcmp($searchOper, "bw")) { //begin with } else if (!strcmp($searchOper, "bn")) { //not begin with } else if (!strcmp($searchOper, "ew")) { //ends with } else if (!strcmp($searchOper, "en")) { //not ends with } else if (!strcmp($searchOper, "cn")) { //contains } else if (!strcmp($searchOper, "nc")) { //not contains } else if (!strcmp($searchOper, "nu")) { //is null } else if (!strcmp($searchOper, "nn")) { //not is null } else if (!strcmp($searchOper, "in")) { //is null } else if (!strcmp($searchOper, "ni")) { //is null } $searchString = Input::get("searchString"); $value = ModelAccount::where($searchField, $searchOper, $searchString)->orderBy(Input::get("sidx"), Input::get("sort"))->take(Input::get("rows"))->offset($offset)->get();//->paginate(Input::get("rows"))->getFrom($offset);//take(20)->offset(10)->get(); $all = ModelAccount::where($searchField, $searchOper, $searchString)->count(); } else { $value = ModelAccount::orderBy(Input::get("sidx"), Input::get("sort"))->take(Input::get("rows"))->offset($offset)->get();//->paginate(Input::get("rows"))->getFrom($offset);//take(20)->offset(10)->get(); $all = ModelAccount::all()->count(); } } $total = ceil($all/Input::get("rows"));//*Input::get("rows") / 10; return '{"page":"'.Input::get("page").'","total":"'.$total.'","records":"'.$all.'","rows":'.$value.'}'; }
4.2.2 分組查詢
具體還沒有分析
4.2.3 Toolbar查詢
jqgrid添加以下代碼:
jQuery("#list4").jqGrid('filterToolbar',{searchOperators : true});
界面效果為:
這個時候的查詢請求為:
這種情況會比較復雜,因為game_auth字段是數據庫中的字段,可能無法做到一定的通用性。
如果同時查詢兩個字段的話,請求為:
服務器端相應的代碼修改為:
public function json() { $searchField=''; $searchOper=''; $searchString=''; $value=''; $all=''; $filters=''; $offset = (Input::get("page") - 1) * Input::get("rows"); $filters = Input::get("filters"); if($filters) { $json_data = json_decode($filters); $groupOp = $json_data->groupOp; $rules = $json_data->rules; //return $rules; $r=''; $number=0; foreach($rules as $rule) { $rule->op = "="; if($number == 0) { $r = $r . ' ' . $rule->field . ' ' . $rule->op . ' ' . $rule->data;//.'"'; } else { if(!strcmp($groupOp, "AND")) { $r = $r . ' and ' . $rule->field . ' ' . $rule->op . ' ' . $rule->data;//.'"'; } else { $r = $r . ' or ' . $rule->field . ' ' . $rule->op . ' ' . $rule->data;//.'"'; } } $number = $number+1; } //$r=$r.' " '; //$r='id = 901 or game_server = 888'; $value = ModelAccount::whereRaw($r)->orderBy(Input::get("sidx"), Input::get("sort"))->take(Input::get("rows"))->offset($offset)->get();//->paginate(Input::get("rows"))->getFrom($offset);//take(20)->offset(10)->get(); $all = ModelAccount::whereRaw($r)->count(); } else { if (!strcmp(Input::get("_search"), "true")) { $searchField = Input::get("searchField"); if($searchField) { $searchOper = Input::get("searchOper"); if (!strcmp($searchOper, "eq")) {//equal $searchOper = "="; } else if (!strcmp($searchOper, "ne")) { //not equal $searchOper = ""; } else if (!strcmp($searchOper, "bw")) { //begin with } else if (!strcmp($searchOper, "bn")) { //not begin with } else if (!strcmp($searchOper, "ew")) { //ends with } else if (!strcmp($searchOper, "en")) { //not ends with } else if (!strcmp($searchOper, "cn")) { //contains } else if (!strcmp($searchOper, "nc")) { //not contains } else if (!strcmp($searchOper, "nu")) { //is null } else if (!strcmp($searchOper, "nn")) { //not is null } else if (!strcmp($searchOper, "in")) { //is null } else if (!strcmp($searchOper, "ni")) { //is null } $searchString = Input::get("searchString"); $value = ModelAccount::where($searchField, $searchOper, $searchString)->orderBy(Input::get("sidx"), Input::get("sort"))->take(Input::get("rows"))->offset($offset)->get();//->paginate(Input::get("rows"))->getFrom($offset);//take(20)->offset(10)->get(); $all = ModelAccount::where($searchField, $searchOper, $searchString)->count(); } else { $game_name=Input::get("game_name"); $game_id=Input::get("game_id"); $game_server=Input::get("game_server"); $game_auth=Input::get("game_auth"); $created_at=Input::get("created_at"); $updated_at=Input::get("updated_at"); $r=''; if($game_name) { $r=$r.' game_name ='.$game_name; } if($game_auth) { if($r) { $r=$r.' and ';} $r=$r.' game_auth ='.$game_auth; } if($game_server) { if($r) { $r=$r.' and ';} $r=$r.' game_server='.$game_server; } if($game_id) { if($r) { $r=$r.' and ';} $r=$r.' game_id='.$game_id; } if($created_at) { if($r) { $r=$r.' and ';} $r=$r.' created_at='.$created_at; } if($updated_at) { if($r) { $r=$r.' and ';} $r=$r.' updated_at='.$updated_at; } $value = ModelAccount::whereRaw($r)->orderBy(Input::get("sidx"), Input::get("sort"))->take(Input::get("rows"))->offset($offset)->get();//->paginate(Input::get("rows"))->getFrom($offset);//take(20)->offset(10)->get(); $all = ModelAccount::whereRaw($r)->count(); } } else { $value = ModelAccount::orderBy(Input::get("sidx"), Input::get("sort"))->take(Input::get("rows"))->offset($offset)->get();//->paginate(Input::get("rows"))->getFrom($offset);//take(20)->offset(10)->get(); $all = ModelAccount::all()->count(); } } $total = ceil($all/Input::get("rows"));//*Input::get("rows") / 10; return '{"page":"'.Input::get("page").'","total":"'.$total.'","records":"'.$all.'","rows":'.$value.'}'; }