Skip to content

Commit

Permalink
Laravel Resource Support (#24)
Browse files Browse the repository at this point in the history
* Implement collection logic

* Implement response logic

* Implement support for AnonymousResourceCollection

* Add helper traits

* Add tests

* Update README
  • Loading branch information
mpyw authored Nov 3, 2019
1 parent 39fe05b commit a063521
Show file tree
Hide file tree
Showing 13 changed files with 581 additions and 0 deletions.
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,52 @@ And you'll get
}
```

## Resource Collection

Lampager supports Laravel's API Resources.

- [Eloquent: API Resources - Laravel - The PHP Framework For Web Artisans](https://laravel.com/docs/6.x/eloquent-resources)

Use helper traits on Resource and ResourceCollection.

```php
use Illuminate\Http\Resources\Json\JsonResource;
use Lampager\Laravel\LampagerResourceTrait;

class PostResource extends JsonResource
{
use LampagerResourceTrait;
}
```

```php
use Illuminate\Http\Resources\Json\ResourceCollection;
use Lampager\Laravel\LampagerResourceCollectionTrait;

class PostResourceCollection extends ResourceCollection
{
use LampagerResourceCollectionTrait;
}
```

```php
$posts = App\Post::lampager()
->orderByDesc('id')
->paginate();

return new PostResourceCollection($posts);
```

```json5
{
"data": [/* ... */],
"has_previous": false,
"previous_cursor": null,
"has_next": true,
"next_cursor": {/* ... */}
}
```

## Classes

Note: See also [lampager/lampager](https://github.com/lampager/lampager).
Expand All @@ -155,6 +201,8 @@ Note: See also [lampager/lampager](https://github.com/lampager/lampager).
| Lampager\\Laravel\\`Processor` | Class | Lampager\\`AbstractProcessor` | Processor implementation for Laravel |
| Lampager\\Laravel\\`PaginationResult` | Class | Lampager\\`PaginationResult` | PaginationResult implementation for Laravel |
| Lampager\\Laravel\\`MacroServiceProvider` | Class | Illuminate\\Support\\`ServiceProvider` | Enable macros chainable from QueryBuilder, ElqouentBuilder and Relation |
| Lampager\\Laravel\\`LampagerResourceTrait` | Trait | | Support for Laravel JsonResource |
| Lampager\\Laravel\\`LampagerResourceCollectionTrait` | Trait | | Support for Laravel ResourceCollection |

`Paginator`, `Processor` and `PaginationResult` are macroable.

Expand Down
48 changes: 48 additions & 0 deletions src/Http/Resources/CollectsPaginationResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace Lampager\Laravel\Http\Resources;

use Illuminate\Http\Resources\CollectsResources;
use Illuminate\Http\Resources\MissingValue;
use Illuminate\Pagination\AbstractPaginator;
use Lampager\Laravel\PaginationResult;

/**
* Trait CollectsPaginationResult
*
* @mixin \Illuminate\Http\Resources\Json\ResourceCollection
*/
trait CollectsPaginationResult
{
use CollectsResources;

/**
* Map the given collection resource into its individual resources.
*
* @param mixed $resource
* @return mixed
*/
protected function collectResource($resource)
{
if ($resource instanceof MissingValue) {
return $resource;
}

$collects = $this->collects();

$this->collection = $collects && !$resource->first() instanceof $collects
? $resource->mapInto($collects)
: $resource->toBase();

if ($resource instanceof AbstractPaginator) {
$resource->setCollection($this->collection);
return $resource;
}
if ($resource instanceof PaginationResult) {
$resource->records = $this->collection;
return $resource;
}

return $this->collection;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Lampager\Laravel\Http\Resources\Json;

use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Lampager\Laravel\Http\Resources\CollectsPaginationResult;

/**
* Class AnonymousPaginationResultAwareResourceCollection
*
* @mixin \Illuminate\Http\Resources\Json\JsonResource
*/
class AnonymousPaginationResultAwareResourceCollection extends AnonymousResourceCollection
{
use MakesAnonymousPaginationResultAwareResourceCollection,
CollectsPaginationResult,
RespondsWithPaginationResult;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace Lampager\Laravel\Http\Resources\Json;

/**
* Trait MakesAnonymousPaginationResultAwareResourceCollection
*
* @mixin \Illuminate\Http\Resources\Json\JsonResource
*/
trait MakesAnonymousPaginationResultAwareResourceCollection
{
/**
* Create a new anonymous resource collection.
*
* @param mixed $resource
* @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
*/
public static function collection($resource)
{
return tap(new AnonymousPaginationResultAwareResourceCollection($resource, static::class), function ($collection) {
if (property_exists(static::class, 'preserveKeys')) {
$collection->preserveKeys = (new static([]))->preserveKeys === true;
}
});
}
}
23 changes: 23 additions & 0 deletions src/Http/Resources/Json/PaginationResultResourceResponse.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace Lampager\Laravel\Http\Resources\Json;

use Illuminate\Http\Resources\Json\PaginatedResourceResponse;
use Illuminate\Support\Arr;

/**
* class PaginationResultResourceResponse
*/
class PaginationResultResourceResponse extends PaginatedResourceResponse
{
/**
* Add the pagination information to the response.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
protected function paginationInformation($request)
{
return Arr::except($this->resource->resource->toArray(), 'records');
}
}
33 changes: 33 additions & 0 deletions src/Http/Resources/Json/RespondsWithPaginationResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace Lampager\Laravel\Http\Resources\Json;

use Illuminate\Http\Resources\Json\PaginatedResourceResponse;
use Illuminate\Pagination\AbstractPaginator;
use Lampager\Laravel\PaginationResult;

/**
* Trait RespondsWithPaginationResult
*
* @mixin \Illuminate\Http\Resources\Json\ResourceCollection
*/
trait RespondsWithPaginationResult
{
/**
* Create an HTTP response that represents the object.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function toResponse($request)
{
if ($this->resource instanceof AbstractPaginator) {
return (new PaginatedResourceResponse($this))->toResponse($request);
}
if ($this->resource instanceof PaginationResult) {
return (new PaginationResultResourceResponse($this))->toResponse($request);
}

return parent::toResponse($request);
}
}
17 changes: 17 additions & 0 deletions src/LampagerResourceCollectionTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Lampager\Laravel;

use Lampager\Laravel\Http\Resources\CollectsPaginationResult;
use Lampager\Laravel\Http\Resources\Json\MakesAnonymousPaginationResultAwareResourceCollection;
use Lampager\Laravel\Http\Resources\Json\RespondsWithPaginationResult;

/**
* Trait LampagerResourceCollectionTrait
*/
trait LampagerResourceCollectionTrait
{
use MakesAnonymousPaginationResultAwareResourceCollection,
CollectsPaginationResult,
RespondsWithPaginationResult;
}
13 changes: 13 additions & 0 deletions src/LampagerResourceTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Lampager\Laravel;

use Lampager\Laravel\Http\Resources\Json\MakesAnonymousPaginationResultAwareResourceCollection;

/**
* Trait LampagerResourceTrait
*/
trait LampagerResourceTrait
{
use MakesAnonymousPaginationResultAwareResourceCollection;
}
27 changes: 27 additions & 0 deletions tests/PostResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Lampager\Laravel\Tests;

use Illuminate\Http\Resources\Json\JsonResource;
use Lampager\Laravel\LampagerResourceTrait;

/**
* Class PostResource
*/
class PostResource extends JsonResource
{
use LampagerResourceTrait;

public $preserveKeys = true;

/**
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return parent::toArray($request) + [
'post_resource' => true,
];
}
}
14 changes: 14 additions & 0 deletions tests/PostResourceCollection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace Lampager\Laravel\Tests;

use Illuminate\Http\Resources\Json\ResourceCollection;
use Lampager\Laravel\LampagerResourceCollectionTrait;

/**
* Class PostResourceCollection
*/
class PostResourceCollection extends ResourceCollection
{
use LampagerResourceCollectionTrait;
}
Loading

0 comments on commit a063521

Please sign in to comment.