From d99d63a26e289ca5f7ad7843533733e0f9c7d4ad Mon Sep 17 00:00:00 2001 From: Arjon Jason Castro Date: Fri, 12 Apr 2019 14:02:07 +0800 Subject: [PATCH] Add helper methods isColumnValid() and getTableColumns() --- README.md | 26 +++++++++++++++++++++++--- src/Searchable.php | 42 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 64 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3b9d7db..370d84c 100644 --- a/README.md +++ b/README.md @@ -58,10 +58,11 @@ class PostsController { public function index() { - return Post::sortByRelevance(!request()->bool('sort_by'))->search(request('search')) - ->when($sortColumn = request('sort_by'), function ($query) use ($sortColumn) { + return Post::sortByRelevance(!request()->bool('sort_by')) + ->search(request('search')) + ->when(Post::isColumnValid($sortColumn = request('sort_by')), function ($query) use ($sortColumn) { $query->orderBy( - \DB::raw($this->model->searchQuery()->getColumn($sortColumn) ?? $sortColumn), + \DB::raw(Post::searchQuery()->getColumn($sortColumn) ?? $sortColumn), request()->bool('descending') ? 'desc' : 'asc' ); }) @@ -341,6 +342,25 @@ $results = [ ]; ``` +## Helper methods available on model + +### isColumnValid + +- Identifies if the column is a valid column, either a regular table column or derived column. +- Useful for checking valid columns to avoid sql injection especially in `orderBy` query. + +```php +Post::isColumnValid(request('sort_by')); +``` + +### getTableColumns + +- Get the table columns. + +```php +Post::getTableColumns(); +``` + ## Credits - Ray Anthony Madrona [@raymadrona](https://github.com/raymadrona), for the tips on using MySQL `LOCATE()` for sort relevance. diff --git a/src/Searchable.php b/src/Searchable.php index f666cbd..cac35fa 100644 --- a/src/Searchable.php +++ b/src/Searchable.php @@ -2,6 +2,7 @@ namespace AjCastro\Searchable; +use Illuminate\Support\Arr; use Illuminate\Support\Facades\Schema; use AjCastro\Searchable\Search\SublimeSearch; @@ -26,13 +27,52 @@ public function searchableColumns() return $this->searchable['columns']; } - if (!array_key_exists($table = $this->getTable(), static::$allSearchableColumns)) { + return static::getTableColumns($this->getTable()); + } + + /** + * Get table columns. + * + * @param string $table + * @return array + */ + public static function getTableColumns($table = null) + { + $table = $table ?? (new static)->getTable(); + + if (!Arr::has(static::$allSearchableColumns, $table)) { static::$allSearchableColumns[$table] = Schema::getColumnListing($table); } return static::$allSearchableColumns[$table]; } + /** + * Identifies if the column is a valid column, either a regular table column or derived column. + * Useful for checking valid columns to avoid sql injection especially in orderBy query. + * + * @param string $column + * @return boolean + */ + public static function isColumnValid($column) + { + $model = new static; + $searchableColumns = $model->searchableColumns(); + + // Derived columns are a key in searchableColumns. + if (array_key_exists($column, $searchableColumns)) { + return true; + } + + // Regular table column can be included in the searchableColumns. + if (in_array($column, $searchableColumns)) { + return true; + } + + // Regular table column from the table + return in_array($column, static::getTableColumns($model->getTable())); + } + /** * Return the searchable joins for the search query. *