diff --git a/README.md b/README.md index aa0b020..b1aed0d 100644 --- a/README.md +++ b/README.md @@ -65,3 +65,31 @@ if (document.getElementById('example')) { ReactDOM.render(, document.getElementById('example')); } ``` + +### Without a model + +Sometimes you need to create a table of data for which there is no model (and the data is some kind of aggregation, so a model would not be appropriate). + +```php +use App\User; +use Illuminate\Http\Request; +use LangleyFoxall\ReactDynamicDataTableLaravelApi\DataTableResponder; + +class UsersController extends Controller +{ + public function dataTable(Request $request) + { + return (new DataTableResponder(DB::table('users')->select(['id', 'name']), $request)) + ->query(function($query) { // Optional, default: none + $query->where('name', 'like', 'B%'); + }) + ->collectionManipulator(function (Collection $collection) { // Optional, default: none + $collection->map(function($user) { + $user->name = title_case($user->name); + }); + }) + ->setPerPage(10) // Optional, default: 15 + ->respond(); + } +} +``` diff --git a/src/DataTableResponder.php b/src/DataTableResponder.php index 4ae5cd8..2067da1 100644 --- a/src/DataTableResponder.php +++ b/src/DataTableResponder.php @@ -4,6 +4,7 @@ use Illuminate\Contracts\Pagination\LengthAwarePaginator; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Query\Builder as QueryBuilder; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Collection; @@ -21,6 +22,11 @@ class DataTableResponder */ private $model; + /** + * @var Builder + */ + private $queryBuilder; + /** * @var Request */ @@ -54,21 +60,28 @@ class DataTableResponder /** * DataTableResponder constructor. * - * @param $className + * @param $classNameOrQueryBuilder * @param Request $request */ - public function __construct($className, Request $request) + public function __construct($classNameOrQueryBuilder, Request $request) { - if (!class_exists($className)) { - throw new InvalidArgumentException('Provided class does not exist.'); - } + if ($classNameOrQueryBuilder instanceof QueryBuilder) { + $this->model = null; + $this->queryBuilder = $classNameOrQueryBuilder; + } else { + if (!class_exists($classNameOrQueryBuilder)) { + throw new InvalidArgumentException('Provided class does not exist.'); + } - $this->model = new $className(); - $this->request = $request; + $this->model = new $classNameOrQueryBuilder(); + $this->queryBuilder = null; - if (!$this->model instanceof Model) { - throw new InvalidArgumentException('Provided class is not an Eloquent model.'); + if (!$this->model instanceof Model) { + throw new InvalidArgumentException('Provided class is not an Eloquent model.'); + } } + + $this->request = $request; } /** @@ -141,7 +154,7 @@ public function setResponseMeta(array $meta = []) */ private function buildQuery(Request $request) { - $query = $this->model->query(); + $query = $this->queryBuilder ?? $this->model->query(); $queryManipulator = $this->queryManipulator; @@ -171,10 +184,10 @@ private function buildQuery(Request $request) } /** - * @param Builder $query + * @param Builder|QueryBuilder $query * @return LengthAwarePaginator */ - private function paginateQuery(Builder $query) + private function paginateQuery($query) { return $query->paginate($this->perPage); } @@ -208,11 +221,11 @@ private function manipulateCollection($results) * `disallow_ordering_by` will always be overwritten * as it is managed internally * - * @param Builder $query + * @param Builder|QueryBuilder $query * @param Collection $collection * @return array */ - private function makeMeta(Builder $query, Collection $collection) + private function makeMeta($query, Collection $collection) { $meta = $this->meta; $out = []; @@ -239,25 +252,28 @@ private function makeMeta(Builder $query, Collection $collection) */ private function disallowOrderingBy() { - $methods = get_class_methods($this->model); $customAttributes = []; - foreach($methods as $method) { - if (!preg_match('/^get(\w+)Attribute$/', $method, $matches)) { - continue; - } + if ($this->model !== null) { + $methods = get_class_methods($this->model); + + foreach($methods as $method) { + if (!preg_match('/^get(\w+)Attribute$/', $method, $matches)) { + continue; + } - if (empty($matches[1])) { - continue; - } + if (empty($matches[1])) { + continue; + } - $customAttribute = Str::snake($matches[1]); + $customAttribute = Str::snake($matches[1]); - if (in_array($customAttribute, array_keys($this->orderByOverrides))) { - continue; - } + if (in_array($customAttribute, array_keys($this->orderByOverrides))) { + continue; + } - $customAttributes[] = $customAttribute; + $customAttributes[] = $customAttribute; + } } return $customAttributes;