From bb0ea19cff036f741789da8537dc58563c85d3ab Mon Sep 17 00:00:00 2001 From: Nur Muhammad Date: Mon, 11 Nov 2024 12:50:02 +0800 Subject: [PATCH] Utilize built-in CodeIgniter query builder functions for filtering and ordering - Refactored filtering and ordering logic to leverage CodeIgniter's built-in query builder functions - Simplify getting column name by a resolver --- src/Config.php | 4 ++ src/DataTables.php | 127 +++++++++++++++++++-------------------------- 2 files changed, 56 insertions(+), 75 deletions(-) diff --git a/src/Config.php b/src/Config.php index 8f3815c..409035a 100644 --- a/src/Config.php +++ b/src/Config.php @@ -15,12 +15,16 @@ class Config 'countAllResults' => 'count_all_results', 'orderBy' => 'order_by', 'where' => 'where', + 'like' => 'like', + 'orLike' => 'or_like', 'limit' => 'limit', 'get' => 'get', 'QBSelect' => 'qb_select', 'getFieldNames' => 'list_fields', 'getResult' => 'result', 'getResultArray' => 'result_array', + 'groupStart' => 'group_start', + 'groupEnd' => 'group_end' ] ]; diff --git a/src/DataTables.php b/src/DataTables.php index 95dc592..542e774 100644 --- a/src/DataTables.php +++ b/src/DataTables.php @@ -171,6 +171,34 @@ protected function setReturnedFieldNames() } } + /** + * Resolves the column name + * + * @param int|string $column The column index or name, depending on `asObject` + * @return string|null The resolved column name or NULL if out of bounds + */ + protected function resolveColumnName($column) + { + if ( ! $this->asObject) { + $fieldIndex = $this->sequenceNumber ? $column - 1 : $column; + + // Skip sequence number and extra column + if ( + ($this->sequenceNumber && $column == 0) OR + $fieldIndex > count($this->returnedFieldNames) - 1 + ) return NULL; + + $column = $this->returnedFieldNames[$fieldIndex]; + } + + // Checking if it using a column alias + $column = isset($this->columnAliases[$column]) + ? $this->columnAliases[$column] + : $column; + + return $column; + } + /** * Add sequence number to the output * @param string $key Used when returning object output as the key @@ -188,38 +216,32 @@ public function addSequenceNumber($key = 'sequenceNumber') protected function filter() { $globalSearch = []; - $columnSearch = []; - - $fieldNamesLength = count($this->returnedFieldNames); // Global column filtering if ($this->request->get('search') && ($keyword = $this->request->get('search')['value']) != '') { foreach ($this->request->get('columns', []) as $request_column) { if (filter_var($request_column['searchable'], FILTER_VALIDATE_BOOLEAN)) { $column = $request_column['data']; - - if ( ! $this->asObject) { - // Skip sequence number - if ($this->sequenceNumber && $column == 0) continue; - - $fieldIndex = $this->sequenceNumber ? $column - 1 : $column; - - // Skip extra column - if ($fieldIndex > $fieldNamesLength - 1) break; - - $column = $this->returnedFieldNames[$fieldIndex]; - } - - // Checking if it using a column alias - $column = isset($this->columnAliases[$column]) - ? $this->columnAliases[$column] - : $column; + $column = $this->resolveColumnName($column); - $globalSearch[] = sprintf("`%s` LIKE '%%%s%%'", $column, $keyword); + if (empty($column)) continue; + + $globalSearch[] = $column; } } } + // Apply global search criteria + if (!empty($globalSearch)) { + $this->queryBuilder->{$this->config->get('groupStart')}(); + + foreach ($globalSearch as $column) { + $this->queryBuilder->{$this->config->get('orLike')}($column, $keyword); + } + + $this->queryBuilder->{$this->config->get('groupEnd')}(); + } + // Individual column filtering foreach ($this->request->get('columns', []) as $request_column) { if ( @@ -227,45 +249,15 @@ protected function filter() ($keyword = $request_column['search']['value']) != '' ) { $column = $request_column['data']; + $column = $this->resolveColumnName($column); + + if (empty($column)) continue; - if ( ! $this->asObject) { - // Skip sequence number - if ($this->sequenceNumber && $column == 0) continue; - - $fieldIndex = $this->sequenceNumber ? $column - 1 : $column; - - // Skip extra column - if ($fieldIndex > $fieldNamesLength - 1) break; - - $column = $this->returnedFieldNames[$fieldIndex]; - } - - // Checking if it using a column alias - $column = isset($this->columnAliases[$column]) - ? $this->columnAliases[$column] - : $column; - - $columnSearch[] = sprintf("`%s` LIKE '%%%s%%'", $column, $keyword); + // Apply column-specific search criteria + $this->queryBuilder->{$this->config->get('like')}($column, $keyword); } } - // Merge global search & column search - $w_filter = ''; - - if ( ! empty($globalSearch)) { - $w_filter = '(' . implode(' OR ', $globalSearch) . ')'; - } - - if ( ! empty($columnSearch)) { - $w_filter = $w_filter === '' ? - implode(' AND ', $columnSearch) : - $w_filter . ' AND ' . implode(' AND ', $columnSearch); - } - - if ($w_filter !== '') { - $this->queryBuilder->{$this->config->get('where')}($w_filter); - } - $this->recordsFiltered = $this->queryBuilder->{$this->config->get('countAllResults')}('', FALSE); } @@ -275,35 +267,20 @@ protected function filter() protected function order() { if ($this->request->get('order') && count($this->request->get('order'))) { - $orders = []; - $fieldNamesLength = count($this->returnedFieldNames); - foreach ($this->request->get('order') as $order) { $column_idx = $order['column']; $request_column = $this->request->get('columns')[$column_idx]; if (filter_var($request_column['orderable'], FILTER_VALIDATE_BOOLEAN)) { $column = $request_column['data']; + $column = $this->resolveColumnName($column); - if ( ! $this->asObject) { - // Skip sequence number - if ($this->sequenceNumber && $column == 0) continue; - - $fieldIndex = $this->sequenceNumber ? $column - 1 : $column; - - // Skip extra column - if ($fieldIndex > $fieldNamesLength - 1) break; - - $column = $this->returnedFieldNames[$fieldIndex]; - } + if (empty($column)) continue; - $orders[] = sprintf('`%s` %s', $column, strtoupper($order['dir'])); + // Apply order + $this->queryBuilder->{$this->config->get('orderBy')}($column, $order['dir']); } } - - if (!empty($orders)) { - $this->queryBuilder->{$this->config->get('orderBy')}(implode(', ', $orders)); - } } }