diff --git a/src/Illuminate/Http/Resources/Json/ResourceCollection.php b/src/Illuminate/Http/Resources/Json/ResourceCollection.php index deab912f16cb..d5fbe2b5e224 100644 --- a/src/Illuminate/Http/Resources/Json/ResourceCollection.php +++ b/src/Illuminate/Http/Resources/Json/ResourceCollection.php @@ -26,10 +26,17 @@ class ResourceCollection extends JsonResource implements Countable, IteratorAggr public $collection; /** - * Determines whether to preserve all query parameters when generating the navigation links. + * Indicates if all existing request query parameters should be added to pagination links. * * @var bool */ + protected $preserveAllQueryParameters = false; + + /** + * The query parameters that should be added to the pagination links. + * + * @var array + */ protected $queryParameters; /** @@ -46,13 +53,26 @@ public function __construct($resource) } /** - * Preserve all query parameters when generating the navigation links. + * Indicate that all current query parameters should be appended to pagination links. + */ + public function preserveQuery() + { + $this->preserveAllQueryParameters = true; + + return $this; + } + + /** + * Preserve the given (or all) query parameters when generating the pagination links. * + * @param array $query * @return $this */ - public function preserveQueryParameters() + public function withQuery(array $query) { - $this->queryParameters = true; + $this->preserveAllQueryParameters = false; + + $this->queryParameters = $query; return $this; } @@ -101,8 +121,10 @@ public function toResponse($request) */ protected function preparePaginatedResponse($request) { - if ($this->queryParameters) { + if ($this->preserveAllQueryParameters) { $this->resource->appends($request->query()); + } elseif (! is_null($this->queryParameters)) { + $this->resource->appends($this->queryParameters); } return (new PaginatedResourceResponse($this))->toResponse($request); diff --git a/tests/Integration/Http/ResourceTest.php b/tests/Integration/Http/ResourceTest.php index aaf08c4e65d8..8136c6d7eb07 100644 --- a/tests/Integration/Http/ResourceTest.php +++ b/tests/Integration/Http/ResourceTest.php @@ -494,7 +494,7 @@ public function testPaginatorResourceCanPreserveQueryParameters() $collection, 3, 1, 2 ); - return PostCollectionResource::make($paginator)->preserveQueryParameters(); + return PostCollectionResource::make($paginator)->preserveQuery(); }); $response = $this->withoutExceptionHandling()->get( @@ -528,6 +528,48 @@ public function testPaginatorResourceCanPreserveQueryParameters() ]); } + public function testPaginatorResourceCanReceiveQueryParameters() + { + Route::get('/', function () { + $collection = collect([new Post(['id' => 2, 'title' => 'Laravel Nova'])]); + $paginator = new LengthAwarePaginator( + $collection, 3, 1, 2 + ); + + return PostCollectionResource::make($paginator)->withQuery(['author' => 'Taylor']); + }); + + $response = $this->withoutExceptionHandling()->get( + '/?framework=laravel&author=Otwell&page=2', ['Accept' => 'application/json'] + ); + + $response->assertStatus(200); + + $response->assertJson([ + 'data' => [ + [ + 'id' => 2, + 'title' => 'Laravel Nova', + ], + ], + 'links' => [ + 'first' => '/?author=Taylor&page=1', + 'last' => '/?author=Taylor&page=3', + 'prev' => '/?author=Taylor&page=1', + 'next' => '/?author=Taylor&page=3', + ], + 'meta' => [ + 'current_page' => 2, + 'from' => 2, + 'last_page' => 3, + 'path' => '/', + 'per_page' => 1, + 'to' => 2, + 'total' => 3, + ], + ]); + } + public function testToJsonMayBeLeftOffOfCollection() { Route::get('/', function () {