diff --git a/README.md b/README.md index 62a951c..5b1f136 100644 --- a/README.md +++ b/README.md @@ -276,6 +276,10 @@ Note: If you want to search on number columns with the query engine, then you ca This will cast the columns int the given types when searching on this columns +You also can use dot syntax if your query has identical fields in different tables + ``` + ->searchColumns(array('category.title', 'job.title', 'phone')) + ``` **orderColumns(..$fields)** Will enable the table to allow ordering only in the given columns. diff --git a/src/Chumper/Datatable/Engines/BaseEngine.php b/src/Chumper/Datatable/Engines/BaseEngine.php index d2cfb1b..88bc00e 100644 --- a/src/Chumper/Datatable/Engines/BaseEngine.php +++ b/src/Chumper/Datatable/Engines/BaseEngine.php @@ -123,6 +123,10 @@ abstract class BaseEngine { */ protected $exactWordSearch = false; + /** + * @var mixed Additional data which passed from server to client. + */ + protected $additionalData = null; function __construct() { @@ -240,6 +244,7 @@ public function make() "sEcho" => intval($this->sEcho), "iTotalRecords" => $this->totalCount(), "iTotalDisplayRecords" => $this->count(), + "aaAdditional" => $this->additionalData, ); return Response::json($output); } @@ -330,6 +335,12 @@ public function setExactMatchColumns($columnNames) return $this; } + public function setAdditionalData($data) + { + $this->additionalData = $data; + return $this; + } + public function getRowClass() { return $this->rowClass; @@ -394,14 +405,16 @@ protected function handlesSearch($value) protected function handleiSortCol_0($value) { if(Input::get('sSortDir_0') == 'desc') - $direction = BaseEngine::ORDER_DESC; + $direction[$value] = BaseEngine::ORDER_DESC; else - $direction = BaseEngine::ORDER_ASC; + $direction[$value] = BaseEngine::ORDER_ASC; + $columns = array(); //check if order is allowed if(empty($this->orderColumns)) { - $this->order(array(0 => $value, 1 => $this->getNameByIndex($value)), $direction); + $columns[] = array(0 => $value, 1 => $this->getNameByIndex($value)); + $this->order($columns, $direction); return; } @@ -419,16 +432,22 @@ protected function handleiSortCol_0($value) } } - $i = 0; - foreach($this->columns as $name => $column) - { - if($i == $value && in_array($name, $cleanNames)) - { - $this->order(array(0 => $value, 1 => $this->orderColumns[array_search($name,$cleanNames)]), $direction); - return; + $iSortingCols = Input::get('iSortingCols'); + $sortingCols[] = $value; + for($i = 1; $i < $iSortingCols; $i++) { + $isc = Input::get('iSortCol_'.$i); + $sortingCols[] = $isc; + $direction[$isc] = Input::get('sSortDir_'.$i); + } + + $allColumns = array_keys($this->columns->all()); + foreach ($sortingCols as $num) { + if(in_array($allColumns[$num], $cleanNames)) { + $columns[] = array(0 => $num, 1 => $this->orderColumns[array_search($allColumns[$num],$cleanNames)]); } - $i++; } + $this->order($columns, $direction); + return; } /** diff --git a/src/Chumper/Datatable/Engines/QueryEngine.php b/src/Chumper/Datatable/Engines/QueryEngine.php index 5a23fc7..775ce85 100644 --- a/src/Chumper/Datatable/Engines/QueryEngine.php +++ b/src/Chumper/Datatable/Engines/QueryEngine.php @@ -41,6 +41,7 @@ class QueryEngine extends BaseEngine { 'orderOrder' => null, 'counter' => 0, 'noGroupByOnCount' => false, + 'emptyAtEnd' => false, ); function __construct($builder) @@ -73,7 +74,10 @@ public function totalCount() $originalBuilder = $this->removeGroupBy($originalBuilder); } - return $originalBuilder->count(); + $qBuilder = $originalBuilder instanceof QueryBuilder ? $originalBuilder : $originalBuilder->getQuery(); + return \DB::table(\DB::raw('('.$originalBuilder->toSql().') as temp_tbl')) + ->mergeBindings($qBuilder) + ->count(); } public function getArray() @@ -100,6 +104,12 @@ public function setSearchWithAlias() return $this; } + public function setEmptyAtEnd() + { + $this->options['emptyAtEnd'] = true; + return $this; + } + public function setNoGroupByOnCount() { $this->options['noGroupByOnCount'] = true; @@ -126,7 +136,10 @@ protected function internalMake(Collection $columns, array $searchColumns = arra if ($this->options['noGroupByOnCount']) { $countBuilder = $this->removeGroupBy($countBuilder); } - $this->options['counter'] = $countBuilder->count(); + $qBuilder = $countBuilder instanceof QueryBuilder ? $countBuilder : $countBuilder->getQuery(); + $this->options['counter'] = \DB::table(\DB::raw('('.$countBuilder->toSql().') as temp_tbl')) + ->mergeBindings($qBuilder) + ->count(); } $builder = $this->doInternalOrder($builder, $columns); @@ -282,23 +295,18 @@ private function doInternalOrder($builder, $columns) //var_dump($this->orderColumn); if(!is_null($this->orderColumn)) { - $i = 0; - foreach($columns as $col) - { - - if($i === (int) $this->orderColumn[0]) - { - if(strrpos($this->orderColumn[1], ':')){ - $c = explode(':', $this->orderColumn[1]); - if(isset($c[2])) - $c[1] .= "($c[2])"; - $builder = $builder->orderByRaw("cast($c[0] as $c[1]) ".$this->orderDirection); - } - else - $builder = $builder->orderBy($col->getName(), $this->orderDirection); - return $builder; + foreach ($this->orderColumn as $ordCol) { + if(strrpos($ordCol[1], ':')){ + $c = explode(':', $ordCol[1]); + if(isset($c[2])) + $c[1] .= "($c[2])"; + $prefix = $this->options['emptyAtEnd'] ? "ISNULL({$c[0]}) asc," : ''; + $builder = $builder->orderByRaw($prefix." cast($c[0] as $c[1]) ".$this->orderDirection[$ordCol[0]]); + } + else { + $prefix = $this->options['emptyAtEnd'] ? "ISNULL({$ordCol[1]}) asc," : ''; + $builder = $builder->orderByRaw($prefix.' '.$ordCol[1].' '.$this->orderDirection[$ordCol[0]]); } - $i++; } } return $builder; diff --git a/src/Chumper/Datatable/Table.php b/src/Chumper/Datatable/Table.php index 3b114ff..a23d4bd 100644 --- a/src/Chumper/Datatable/Table.php +++ b/src/Chumper/Datatable/Table.php @@ -58,6 +58,11 @@ class Table { */ protected $className; + /** + * @var String The footer's display mode + */ + protected $footerMode = 'hidden'; + /** * @var String The view used to render the table */ @@ -304,13 +309,14 @@ public function getViewParameters() $this->createMapping(); } return array( - 'options' => $this->convertData(array_merge($this->options, $this->callbacks)), + 'options' => $this->convertData($this->options, $this->callbacks), 'values' => $this->customValues, 'data' => $this->data, 'columns' => array_combine($this->aliasColumns,$this->columns), 'noScript' => $this->noScript, 'id' => $this->idName, 'class' => $this->className, + 'footerMode'=> $this->footerMode, ); } @@ -325,7 +331,19 @@ public function noScript() return $this; } - private function convertData($options) { + /** + * Set the footer display mode. + * + * @param $value the one of next values: 'hidden', 'columns', 'empty' + * @return $this + */ + public function showFooter($value = 'columns') + { + $this->footerMode = $value; + return $this; + } + + private function convertData($options, $callbacks = null) { $is_obj = false; $first = true; $data = ""; @@ -342,11 +360,7 @@ private function convertData($options) { $data .= json_encode($k) . ":"; } if (is_string($o)) { - if (@preg_match("#^\s*function\s*\([^\)]*#", $o)) { - $data .= $o; - } else { - $data .= json_encode($o); - } + $data .= json_encode($o); } else { if (is_array($o)) { $data .= $this->convertData($o); @@ -355,6 +369,12 @@ private function convertData($options) { } } } + if ($callbacks) { + foreach ($callbacks as $k => $o) { + $data .= empty($data) ? '' : ",\n"; + $data .= json_encode($k) . ":" . $o; + } + } if ($is_obj) { $data = "{ $data }"; @@ -377,7 +397,7 @@ public function script($view = null) } return View::make($this->script_view,array( - 'options' => $this->convertData(array_merge($this->options, $this->callbacks)), + 'options' => $this->convertData($this->options, $this->callbacks), 'id' => $this->idName, )); } diff --git a/src/views/template.blade.php b/src/views/template.blade.php index d6c2264..b087b8c 100644 --- a/src/views/template.blade.php +++ b/src/views/template.blade.php @@ -11,6 +11,15 @@ @endforeach + @if ($footerMode !== 'hidden') + + + @foreach($columns as $i => $c) + @if($footerMode === 'columns') {{ $c }} @endif + @endforeach + + + @endif @foreach($data as $d)