Skip to content

Commit 590dcac

Browse files
committed
Fix filtering & ordering when using arrays data source
1 parent 34d58ef commit 590dcac

File tree

2 files changed

+100
-28
lines changed

2 files changed

+100
-28
lines changed

src/DataTables.php

Lines changed: 85 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ class DataTables
1313
protected $request;
1414
protected $queryBuilder;
1515
protected $columnAliases = [];
16+
protected $fieldNames = [];
17+
protected $returnedFieldNames = [];
1618
protected $formatters = [];
1719
protected $extraColumns = [];
1820

@@ -45,6 +47,11 @@ public function __construct($queryBuilder, $ciVersion = '4')
4547
$qbSelect = $replection->getValue($queryBuilder);
4648
$this->columnAliases = Helper::getColumnAliases($qbSelect);
4749

50+
// When getting the field names, the query builder will be changed
51+
// So we need to make a clone to keep the original
52+
$queryBuilderClone = clone $queryBuilder;
53+
$this->fieldNames = Helper::getFieldNames($queryBuilderClone, $this->config);
54+
4855
$this->recordsTotal = $this->queryBuilder->{$this->config->get('countAllResults')}('', FALSE);
4956
}
5057

@@ -106,6 +113,30 @@ public function except($columns)
106113
return $this;
107114
}
108115

116+
/**
117+
* Set the returned field names base on only & except
118+
* We will use the only first if defined
119+
* So you must use either only or except (not both)
120+
*/
121+
protected function setReturnedFieldNames()
122+
{
123+
if ( ! empty($this->only)) {
124+
foreach ($this->fieldNames as $field) {
125+
if (in_array($field, $this->only)) {
126+
array_push($this->returnedFieldNames, $field);
127+
}
128+
}
129+
} elseif ( ! empty($this->except)) {
130+
foreach ($this->fieldNames as $field) {
131+
if ( ! in_array($field, $this->except)) {
132+
array_push($this->returnedFieldNames, $field);
133+
}
134+
}
135+
} else {
136+
$this->returnedFieldNames = $this->fieldNames;
137+
}
138+
}
139+
109140
/**
110141
* Add sequence number to the output
111142
* @param string $key Used when returning object output as the key
@@ -129,10 +160,25 @@ protected function filter()
129160
if ($this->request->get('search') && ($keyword = $this->request->get('search')['value']) != '') {
130161
foreach ($this->request->get('columns') as $request_column) {
131162
if (filter_var($request_column['searchable'], FILTER_VALIDATE_BOOLEAN)) {
163+
$column = $request_column['data'];
164+
165+
if ( ! $this->asObject) {
166+
// Skip sequence number
167+
if ($column == 0) continue;
168+
169+
$fieldIndex = $this->sequenceNumber ? $column - 1 : $column;
170+
171+
// Skip extra column
172+
$fieldNamesLength = count($this->returnedFieldNames);
173+
if ($fieldIndex > $fieldNamesLength - 1) break;
174+
175+
$column = $this->returnedFieldNames[$fieldIndex];
176+
}
177+
132178
// Checking if it using a column alias
133-
$column = isset($this->columnAliases[$request_column['data']])
134-
? $this->columnAliases[$request_column['data']]
135-
: $request_column['data'];
179+
$column = isset($this->columnAliases[$column])
180+
? $this->columnAliases[$column]
181+
: $column;
136182

137183
$globalSearch[] = sprintf("`%s` LIKE '%%%s%%'", $column, $keyword);
138184
}
@@ -145,10 +191,25 @@ protected function filter()
145191
filter_var($request_column['searchable'], FILTER_VALIDATE_BOOLEAN) &&
146192
($keyword = $request_column['search']['value']) != ''
147193
) {
194+
$column = $request_column['data'];
195+
196+
if ( ! $this->asObject) {
197+
// Skip sequence number
198+
if ($column == 0) continue;
199+
200+
$fieldIndex = $this->sequenceNumber ? $column - 1 : $column;
201+
202+
// Skip extra column
203+
$fieldNamesLength = count($this->returnedFieldNames);
204+
if ($fieldIndex > $fieldNamesLength - 1) break;
205+
206+
$column = $this->returnedFieldNames[$fieldIndex];
207+
}
208+
148209
// Checking if it using a column alias
149-
$column = isset($this->columnAliases[$request_column['data']])
150-
? $this->columnAliases[$request_column['data']]
151-
: $request_column['data'];
210+
$column = isset($this->columnAliases[$column])
211+
? $this->columnAliases[$column]
212+
: $column;
152213

153214
$columnSearch[] = sprintf("`%s` LIKE '%%%s%%'", $column, $keyword);
154215
}
@@ -184,9 +245,23 @@ protected function order()
184245
foreach ($this->request->get('order') as $order) {
185246
$column_idx = $order['column'];
186247
$request_column = $this->request->get('columns')[$column_idx];
187-
$column = $request_column['data'];
188-
248+
189249
if (filter_var($request_column['orderable'], FILTER_VALIDATE_BOOLEAN)) {
250+
$column = $request_column['data'];
251+
252+
if ( ! $this->asObject) {
253+
// Skip sequence number
254+
if ($column == 0) continue;
255+
256+
$fieldIndex = $this->sequenceNumber ? $column - 1 : $column;
257+
258+
// Skip extra column
259+
$fieldNamesLength = count($this->returnedFieldNames);
260+
if ($fieldIndex > $fieldNamesLength - 1) break;
261+
262+
$column = $this->returnedFieldNames[$fieldIndex];
263+
}
264+
190265
$orders[] = sprintf('`%s` %s', $column, strtoupper($order['dir']));
191266
}
192267
}
@@ -223,31 +298,13 @@ public function asObject()
223298
*/
224299
public function generate()
225300
{
301+
$this->setReturnedFieldNames();
226302
$this->filter();
227303
$this->order();
228304
$this->limit();
229305

230306
$result = $this->queryBuilder->{$this->config->get('get')}();
231307

232-
$fields = $result->{$this->config->get('getFieldNames')}();
233-
$fieldsFiltered = [];
234-
235-
if ( ! empty($this->only)) {
236-
foreach ($this->only as $field) {
237-
if (in_array($field, $fields)) {
238-
array_push($fieldsFiltered, $field);
239-
}
240-
}
241-
} elseif ( ! empty($this->except)) {
242-
foreach ($fields as $field) {
243-
if ( ! in_array($field, $this->except)) {
244-
array_push($fieldsFiltered, $field);
245-
}
246-
}
247-
} else {
248-
$fieldsFiltered = $fields;
249-
}
250-
251308
$output = [];
252309

253310
$sequenceNumber = $this->request->get('start') + 1;
@@ -257,7 +314,7 @@ public function generate()
257314
$row[$this->sequenceNumberKey] = $sequenceNumber++;
258315
}
259316

260-
foreach ($fieldsFiltered as $field) {
317+
foreach ($this->returnedFieldNames as $field) {
261318
$row[$field] = isset($this->formatters[$field])
262319
? $this->formatters[$field]($res->$field, $res)
263320
: $res->$field;

src/Helper.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,19 @@ public static function getColumnAliases($qbSelect)
3333

3434
return $columnAliases;
3535
}
36+
37+
/**
38+
* Get all select fields result
39+
* Used when we use the arrays data source for ordering
40+
* @param $queryBuilder
41+
* @param Config $config
42+
*
43+
* @return array
44+
*/
45+
public static function getFieldNames($queryBuilder, $config)
46+
{
47+
return $queryBuilder->where('0=1') // We don't need any data
48+
->{$config->get('get')}()
49+
->{$config->get('getFieldNames')}();
50+
}
3651
}

0 commit comments

Comments
 (0)