Skip to content

Commit 2278d39

Browse files
author
Robert Allport
authored
Merge pull request #10 from AdamGaskins/arrayable
Add support for JsonResources (and any other Arrayables/JsonSerializables)
2 parents aedad49 + bc4da2b commit 2278d39

File tree

4 files changed

+62
-10
lines changed

4 files changed

+62
-10
lines changed

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,11 @@ Optionally, the trait could be imported within a base controller.
4646

4747
## Available methods
4848

49-
5049
#### `respondNotFound(string|Exception $message, ?string $key = 'error')`
5150

5251
Returns a `404` HTTP status code, an excpetion object can optionally be passed.
5352

54-
#### `respondWithSuccess(?array $contents = [])`
53+
#### `respondWithSuccess(array|Arrayable|JsonSerializable|null $contents = [])`
5554

5655
Returns a `200` HTTP status code
5756

@@ -71,11 +70,11 @@ Returns a `403` HTTP status code
7170

7271
Returns a `400` HTTP status code
7372

74-
#### `respondCreated(?array $data = [])`
73+
#### `respondCreated(array|Arrayable|JsonSerializable|null $data = [])`
7574

7675
Returns a `201` HTTP status code, with response optional data
7776

78-
#### `respondNoContent(?array $data = [])`
77+
#### `respondNoContent(array|Arrayable|JsonSerializable|null $data = [])`
7978

8079
Returns a `204` HTTP status code, with optional response data. Strictly speaking, the response body should be empty. However, functionality to optionally return data was added to handle legacy projects. Within your own projects, you can simply call the method, omitting parameters, to generate a correct `204` response i.e. `return $this->respondNoContent()`
8180

@@ -93,7 +92,11 @@ I wanted to add a simple trait that kept this consistent, in this case:
9392

9493
`$this->respondError('Ouch')`
9594

96-
This package is intended to be used **alongside** Laravel's [API resources](https://laravel.com/docs/8.x/eloquent-resources) and in no way replaces them.
95+
This package is intended to be used **alongside** Laravel's [API resources](https://laravel.com/docs/8.x/eloquent-resources) and in no way replaces them:
96+
97+
```php
98+
$this->respondCreated(PostResource::make($post));
99+
```
97100

98101
## Contribution
99102

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
],
1919
"require": {
2020
"php": "^7.4 | ^8.0",
21-
"illuminate/support": "^6.0|^7.0|^8.0"
21+
"illuminate/support": "^6.0|^7.0|^8.0",
22+
"ext-json": "*"
2223
},
2324
"require-dev": {
2425
"orchestra/testbench": "^4.0|^5.0|^6.0",

src/ApiResponseHelpers.php

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
namespace F9Web;
66

77
use Exception;
8+
use Illuminate\Contracts\Support\Arrayable;
89
use Illuminate\Http\JsonResponse;
10+
use JsonSerializable;
911
use Symfony\Component\HttpFoundation\Response;
1012

1113
use function response;
@@ -32,8 +34,13 @@ public function respondNotFound(
3234
);
3335
}
3436

35-
public function respondWithSuccess(?array $contents = []): JsonResponse
37+
/**
38+
* @param array|Arrayable|JsonSerializable|null $contents
39+
*/
40+
public function respondWithSuccess($contents = []): JsonResponse
3641
{
42+
$contents = $this->morphToArray($contents);
43+
3744
$data = [] === $contents
3845
? ['success' => true]
3946
: $contents;
@@ -70,8 +77,13 @@ public function respondError(?string $message = null): JsonResponse
7077
);
7178
}
7279

73-
public function respondCreated(?array $data = []): JsonResponse
80+
/**
81+
* @param array|Arrayable|JsonSerializable|null $data
82+
*/
83+
public function respondCreated($data = []): JsonResponse
7484
{
85+
$data = $this->morphToArray($data);
86+
7587
return $this->apiResponse($data, Response::HTTP_CREATED);
7688
}
7789

@@ -102,14 +114,36 @@ public function respondTeapot(): JsonResponse
102114
Response::HTTP_I_AM_A_TEAPOT
103115
);
104116
}
105-
106-
public function respondNoContent(?array $data = []): JsonResponse
117+
118+
/**
119+
* @param array|Arrayable|JsonSerializable|null $data
120+
*/
121+
public function respondNoContent($data = []): JsonResponse
107122
{
123+
$data = $this->morphToArray($data);
124+
108125
return $this->apiResponse($data, Response::HTTP_NO_CONTENT);
109126
}
110127

111128
private function apiResponse(array $data, int $code = 200): JsonResponse
112129
{
113130
return response()->json($data, $code);
114131
}
132+
133+
/**
134+
* @param array|Arrayable|JsonSerializable|null $data
135+
* @return array|null
136+
*/
137+
private function morphToArray($data)
138+
{
139+
if ($data instanceof Arrayable) {
140+
return $data->toArray();
141+
}
142+
143+
if ($data instanceof JsonSerializable) {
144+
return $data->jsonSerialize();
145+
}
146+
147+
return $data;
148+
}
115149
}

tests/ResponseTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use DomainException;
88
use F9Web\ApiResponseHelpers;
99
use Illuminate\Http\JsonResponse;
10+
use Illuminate\Support\Collection;
1011
use Symfony\Component\HttpFoundation\Response;
1112

1213
class ResponseTest extends TestCase
@@ -50,6 +51,10 @@ public function testRespondWithSuccess(): void
5051
$response = $this->service->respondWithSuccess(['super' => 'response', 'yes' => 123]);
5152
self::assertJsonStringEqualsJsonString('{"super":"response","yes":123}', $response->getContent());
5253
self::assertEquals(['super' => 'response', 'yes' => 123], $response->getData(true));
54+
55+
$response = $this->service->respondWithSuccess(new Collection(['super' => 'response', 'yes' => 123]));
56+
self::assertJsonStringEqualsJsonString('{"super":"response","yes":123}', $response->getContent());
57+
self::assertEquals(['super' => 'response', 'yes' => 123], $response->getData(true));
5358
}
5459

5560
public function testRespondOk(): void
@@ -112,6 +117,15 @@ public function testRespondCreated(): void
112117
self::assertEquals(Response::HTTP_CREATED, $response->getStatusCode());
113118
self::assertJsonStringEqualsJsonString('[]', $response->getContent());
114119
self::assertEquals([], $response->getData(true));
120+
121+
$response = $this->service->respondCreated([ 'id' => 123, 'title' => 'ABC' ]);
122+
self::assertJsonStringEqualsJsonString('{"id":123,"title":"ABC"}', $response->getContent());
123+
self::assertEquals([ 'id' => 123, 'title' => 'ABC' ], $response->getData(true));
124+
125+
$response = $this->service->respondCreated(new Collection([ 'id' => 123, 'title' => 'ABC' ]));
126+
self::assertJsonStringEqualsJsonString('{"id":123,"title":"ABC"}', $response->getContent());
127+
self::assertEquals([ 'id' => 123, 'title' => 'ABC' ], $response->getData(true));
128+
self::assertEquals(Response::HTTP_CREATED, $response->getStatusCode());
115129
}
116130

117131
public function testRespondFailedValidation(): void

0 commit comments

Comments
 (0)