diff --git a/src/CollectionDataTable.php b/src/CollectionDataTable.php index b581cc3b..6c733cbc 100644 --- a/src/CollectionDataTable.php +++ b/src/CollectionDataTable.php @@ -16,6 +16,13 @@ class CollectionDataTable extends DataTableAbstract */ public $collection; + /** + * Collection object. + * + * @var \Illuminate\Support\Collection + */ + public $merged; + /** * Collection object. * @@ -66,6 +73,7 @@ public function __construct(Collection $collection) $this->request = app('datatables.request'); $this->config = app('datatables.config'); $this->collection = $collection; + $this->merged = collect(); $this->original = $collection; $this->columns = array_keys($this->serialize($collection->first())); } @@ -216,16 +224,9 @@ private function revertIndexColumn($mDataSupport) } } - /** - * Perform global search for the given keyword. - * - * @param string $keyword - */ - protected function globalSearch($keyword) + protected function search($keyword) { - $keyword = $this->config->isCaseInsensitive() ? Str::lower($keyword) : $keyword; - - $this->collection = $this->collection->filter(function ($row) use ($keyword) { + return $this->collection->filter(function ($row) use ($keyword) { $this->isFilterApplied = true; $data = $this->serialize($row); @@ -241,6 +242,7 @@ protected function globalSearch($keyword) } $value = $this->config->isCaseInsensitive() ? Str::lower($value) : $value; + if (Str::contains($value, $keyword)) { return true; } @@ -250,6 +252,36 @@ protected function globalSearch($keyword) }); } + /** + * Perform global search for the given keyword. + * + * @param string $keyword + */ + protected function globalSearch($keyword) + { + $keyword = $this->config->isCaseInsensitive() ? Str::lower($keyword) : $keyword; + + $this->collection = $this->search($keyword); + } + + /** + * Perform multiple search for the given keyword. + * + * @param string $keyword + */ + protected function multiSearch($keywords) + { + $keywords->each(function ($keyword) { + $keyword = $this->config->isCaseInsensitive() ? Str::lower($keyword) : $keyword; + + $mergedCollection = $this->search($keyword); + + $this->merged = $this->merged->merge($mergedCollection); + }); + + $this->collection = $this->merged->unique(); + } + /** * Perform default query orderBy clause. */ diff --git a/src/DataTableAbstract.php b/src/DataTableAbstract.php index 38e63c6c..9599ffea 100644 --- a/src/DataTableAbstract.php +++ b/src/DataTableAbstract.php @@ -464,6 +464,32 @@ public function startsWithSearch($state = true) return $this; } + /** + * Set multi_term search config at runtime. + * + * @param bool $state + * @return $this + */ + public function multiTermSearch($state = true) + { + $this->config->set('datatables.search.multi_term', $state); + + return $this; + } + + /** + * Set multiple search config at runtime. + * + * @param bool $state + * @return $this + */ + public function multipleSearch($state = true) + { + $this->config->set('datatables.search.multiple', $state); + + return $this; + } + /** * Set total records manually. * @@ -655,6 +681,12 @@ public function filtering() { $keyword = $this->request->keyword(); + if ($this->config->isMultiple()) { + $this->smartMultiSearch($keyword); + + return; + } + if ($this->config->isMultiTerm()) { $this->smartGlobalSearch($keyword); @@ -681,6 +713,22 @@ protected function smartGlobalSearch($keyword) }); } + /** + * Perform multiple search by splitting keyword into + * individual words and searches for each of them. + * + * @param string $keyword + */ + protected function smartMultiSearch($keyword) + { + $this->multiSearch( + collect(explode(' ', $keyword)) + ->reject(function ($keyword) { + return trim($keyword) === ''; + }) + ); + } + /** * Perform global search for the given keyword. * diff --git a/src/QueryDataTable.php b/src/QueryDataTable.php index 929654e4..3f209dc4 100644 --- a/src/QueryDataTable.php +++ b/src/QueryDataTable.php @@ -703,14 +703,9 @@ protected function getNullsLastSql($column, $direction) ); } - /** - * Perform global search for the given keyword. - * - * @param string $keyword - */ - protected function globalSearch($keyword) + protected function search($keyword, $multiple = false) { - $this->query->where(function ($query) use ($keyword) { + $this->query->where(function ($query) use ($keyword, $multiple) { collect($this->request->searchableColumnIndex()) ->map(function ($index) { return $this->getColumnName($index); @@ -718,18 +713,50 @@ protected function globalSearch($keyword) ->reject(function ($column) { return $this->isBlacklisted($column) && ! $this->hasFilterColumn($column); }) - ->each(function ($column) use ($keyword, $query) { - if ($this->hasFilterColumn($column)) { - $this->applyFilterColumn($query, $column, $keyword, 'or'); + ->each(function ($column) use ($keyword, $query, $multiple) { + if ($multiple) { + $keyword->each(function ($keyword) use ($query, $column) { + if ($this->hasFilterColumn($column)) { + $this->applyFilterColumn($query, $column, $keyword, 'or'); + } else { + $this->compileQuerySearch($query, $column, $keyword); + } + + $this->isFilterApplied = true; + }); } else { - $this->compileQuerySearch($query, $column, $keyword); - } + if ($this->hasFilterColumn($column)) { + $this->applyFilterColumn($query, $column, $keyword, 'or'); + } else { + $this->compileQuerySearch($query, $column, $keyword); + } - $this->isFilterApplied = true; + $this->isFilterApplied = true; + } }); }); } + /** + * Perform global search for the given keyword. + * + * @param string $keyword + */ + protected function globalSearch($keyword) + { + $this->search($keyword); + } + + /** + * Perform multiple search for the given keyword. + * + * @param string $keyword + */ + protected function multiSearch($keywords) + { + $this->search($keywords, true); + } + /** * Append debug parameters on output. * diff --git a/src/Utilities/Config.php b/src/Utilities/Config.php index 67a0f393..7e23e854 100644 --- a/src/Utilities/Config.php +++ b/src/Utilities/Config.php @@ -95,6 +95,16 @@ public function isMultiTerm() return $this->repository->get('datatables.search.multi_term', true); } + /** + * Check if dataTable config uses multiple searching. + * + * @return bool + */ + public function isMultiple() + { + return $this->repository->get('datatables.search.multiple', false); + } + /** * Check if dataTable config uses starts_with searching. * diff --git a/src/config/datatables.php b/src/config/datatables.php index ed2e36f7..fccad859 100644 --- a/src/config/datatables.php +++ b/src/config/datatables.php @@ -16,6 +16,11 @@ */ 'multi_term' => true, + /* + * Multiple search will explode search keyword using spaces resulting into multiple search. + */ + 'multiple' => false, + /* * Case insensitive will search the keyword in lower case format. * SQL: LOWER(column) LIKE LOWER(keyword) @@ -66,6 +71,7 @@ /* * Nulls last sql pattern for PostgreSQL & Oracle. * For MySQL, use 'CASE WHEN :column IS NULL THEN 1 ELSE 0 END, :column :direction' + * For PostgreSQL & Oracle use ':column :direction NULLS LAST' */ 'nulls_last_sql' => ':column :direction NULLS LAST',