Skip to content

Commit

Permalink
pref: refactor response
Browse files Browse the repository at this point in the history
  • Loading branch information
jiannei committed Oct 13, 2023
1 parent 82aeba6 commit 586b0dc
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 184 deletions.
4 changes: 2 additions & 2 deletions src/Support/Facades/Format.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@
use Illuminate\Support\Facades\Facade as IlluminateFacade;

/**
* @method static JsonResponse response($data = null, string $message = '', int $code = 200, $errors = null, array $headers = [], int $option = 0, string $from = 'success')
* @method static array data($data, ?string $message, int $code, $errors = null)
* @method static array|\Jiannei\Response\Laravel\Support\Format data($data = null)
* @method static array paginator(AbstractPaginator|AbstractCursorPaginator $resource)
* @method static array resourceCollection(ResourceCollection $collection)
* @method static array jsonResource(JsonResource $resource)
* @method static JsonResponse response()
*
* @see \Jiannei\Response\Laravel\Support\Format
*/
Expand Down
133 changes: 69 additions & 64 deletions src/Support/Format.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,61 +29,41 @@ class Format
{
use Macroable;

protected ?array $data = null;
protected int $statusCode = 200;

/**
* Return a new JSON response from the application.
*
* @param mixed|null $data
* @param string $message
* @param int|\BackedEnum $code
* @param null $errors
* @param array $headers
* @param int $option
* @param string $from
* @return JsonResponse
*/
public function response(
mixed $data = null,
string $message = '',
int|\BackedEnum $code = 200,
$errors = null,
array $headers = [],
int $option = 0,
string $from = 'success'
): JsonResponse {
return new JsonResponse(
$this->data($data, $message, $code, $errors, $from),
$this->formatStatusCode($code, $from),
$headers,
$option
);
public function response(): JsonResponse
{
return new JsonResponse($this->data, $this->statusCode);
}

/**
* Format return data structure.
*
* @param JsonResource|array|mixed $data
* @param string|null $message
* @param int|\BackedEnum $code
* @param null $errors
* @return array
*/
public function data($data, ?string $message, int|\BackedEnum $code, $errors = null, $from = 'success'): array
public function data($data = null): static|array
{
$data = match (true) {
$data instanceof ResourceCollection => $this->resourceCollection($data),
$data instanceof JsonResource => $this->jsonResource($data),
$data instanceof AbstractPaginator || $data instanceof AbstractCursorPaginator => $this->paginator($data),
$data instanceof Arrayable || (is_object($data) && method_exists($data, 'toArray')) => $data->toArray(),
default => Arr::wrap($data)
};
if (is_null($data)) {
return $this->data;
}

return $this->formatDataFields([
'status' => $this->formatStatus($code, $from),
'code' => $this->formatBusinessCode($code),
'message' => $this->formatMessage($code, $message),
'data' => $data ?: (object) $data,
'error' => $errors ?: (object) [],
]);
$bizCode = $data['code'] ?? 200;
$oriData = $data['data'] ?? null;
$message = $data['message'] ?? '';
$error = $data['error'] ?? [];

return tap($this, function () use ($bizCode, $oriData, $message, $error) {
$this->statusCode = $this->formatStatusCode($this->formatBusinessCode($bizCode), $oriData);

$this->data = $this->formatDataFields([
'status' => $this->formatStatus($this->statusCode),
'code' => $this->formatBusinessCode($bizCode),
'message' => $this->formatMessage($this->formatBusinessCode($bizCode), $message),
'data' => $this->formatData($oriData),
'error' => $this->formatError($error),
]);
});
}

/**
Expand Down Expand Up @@ -125,20 +105,38 @@ public function jsonResource(JsonResource $resource): array
return value($this->formatJsonResource(), $resource);
}

/**
* Format data.
*
* @param $data
* @return array|object
*/
protected function formatData($data): array|object
{
$formattedData = match (true) {
$data instanceof ResourceCollection => $this->resourceCollection($data),
$data instanceof JsonResource => $this->jsonResource($data),
$data instanceof AbstractPaginator || $data instanceof AbstractCursorPaginator => $this->paginator($data),
$data instanceof Arrayable || (is_object($data) && method_exists($data, 'toArray')) => $data->toArray(),
default => Arr::wrap($data)
};

return $formattedData ?: (object) $data;
}

/**
* Format return message.
*
* @param int|\BackedEnum $code
* @param string|null $message
* @param int $code
* @param string $message
* @return string|null
*/
protected function formatMessage(int|\BackedEnum $code, ?string $message): ?string
protected function formatMessage(int $code, string $message = ''): ?string
{
$localizationKey = join('.', [Config::get('response.locale', 'enums'), $this->formatBusinessCode($code)]);
$localizationKey = join('.', [Config::get('response.locale', 'enums'), $code]);

return match (true) {
! $message && Lang::has($localizationKey) => Lang::get($localizationKey),
$code instanceof \BackedEnum && method_exists($code, 'description') => $code->description(),
!$message && Lang::has($localizationKey) => Lang::get($localizationKey),
default => $message
};
}
Expand All @@ -157,13 +155,11 @@ protected function formatBusinessCode(int|\BackedEnum $code): int
/**
* Format http status description.
*
* @param int|\BackedEnum $code
* @param int $statusCode
* @return string
*/
protected function formatStatus(int|\BackedEnum $code, string $from = 'success'): string
protected function formatStatus(int $statusCode): string
{
$statusCode = $this->formatStatusCode($code, $from);

return match (true) {
($statusCode >= 400 && $statusCode <= 499) => 'error',// client error
($statusCode >= 500 && $statusCode <= 599) => 'fail',// service error
Expand All @@ -174,15 +170,13 @@ protected function formatStatus(int|\BackedEnum $code, string $from = 'success')
/**
* Http status code.
*
* @param int|\BackedEnum $code
* @param string $from
* @param int $code
* @param $oriData
* @return int
*/
protected function formatStatusCode(int|\BackedEnum $code, string $from = 'success'): int
protected function formatStatusCode(int $code, $oriData): int
{
$code = $from === 'fail' ? (Config::get('response.error_code') ?: $code) : $code;

return (int) substr($this->formatBusinessCode($code), 0, 3);
return (int) substr(is_null($oriData) ? (Config::get('response.error_code') ?: $code) : $code, 0, 3);
}

/**
Expand Down Expand Up @@ -244,6 +238,17 @@ protected function formatMeta($collection): array
};
}

/**
* Format error.
*
* @param array $error
* @return array|object
*/
protected function formatError(array $error): object|array
{
return Config::get('app.debug') ? $error : (object) [];
}

/**
* Format response data fields.
*
Expand All @@ -255,7 +260,7 @@ protected function formatDataFields(array $data): array
$formatConfig = \config('response.format.config', []);

foreach ($formatConfig as $key => $config) {
if (! Arr::has($data, $key)) {
if (!Arr::has($data, $key)) {
continue;
}

Expand All @@ -268,7 +273,7 @@ protected function formatDataFields(array $data): array
$key = $alias;
}

if (! $show) {
if (!$show) {
$data = Arr::except($data, $key);
}
}
Expand Down
26 changes: 9 additions & 17 deletions src/Support/Traits/JsonResponseTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,35 +60,31 @@ public function created($data = [], string $message = '', string $location = '')
*/
public function noContent(string $message = ''): JsonResponse
{
return $this->success([], $message, 204);
return $this->success(message: $message, code: 204);
}

/**
* Alias of success method, no need to specify data parameter.
*
* @param string $message
* @param int|\BackedEnum $code
* @param array $headers
* @param int $option
* @return JsonResponse
*/
public function ok(string $message = '', int|\BackedEnum $code = 200, array $headers = [], int $option = 0): JsonResponse
public function ok(string $message = '', int|\BackedEnum $code = 200): JsonResponse
{
return $this->success([], $message, $code, $headers, $option);
return $this->success(message: $message, code: $code);
}

/**
* Alias of the successful method, no need to specify the message and data parameters.
* You can use ResponseCodeEnum to localize the message.
*
* @param int|\BackedEnum $code
* @param array $headers
* @param int $option
* @return JsonResponse
*/
public function localize(int|\BackedEnum $code = 200, array $headers = [], int $option = 0): JsonResponse
public function localize(int|\BackedEnum $code = 200): JsonResponse
{
return $this->ok('', $code, $headers, $option);
return $this->ok(code: $code);
}

/**
Expand Down Expand Up @@ -157,13 +153,11 @@ public function errorInternal(string $message = ''): void
* @param string $message
* @param int|\BackedEnum $code
* @param null $errors
* @param array $headers
* @param int $option
* @return JsonResponse
*/
public function fail(string $message = '', int|\BackedEnum $code = 500, $errors = null, array $headers = [], int $option = 0): JsonResponse
public function fail(string $message = '', int|\BackedEnum $code = 500, $errors = null): JsonResponse
{
$response = Format::response(null, $message, $code, $errors, $headers, $option, 'fail');
$response = Format::data(compact('message', 'code', 'errors'))->response();

if (is_null($errors)) {
$response->throwResponse();
Expand All @@ -178,12 +172,10 @@ public function fail(string $message = '', int|\BackedEnum $code = 500, $errors
* @param mixed $data
* @param string $message
* @param int|\BackedEnum $code
* @param array $headers
* @param int $option
* @return JsonResponse
*/
public function success($data = [], string $message = '', int|\BackedEnum $code = 200, array $headers = [], int $option = 0)
public function success($data = [], string $message = '', int|\BackedEnum $code = 200)
{
return Format::response($data, $message, $code, null, $headers, $option);
return Format::data(compact('data', 'message', 'code'))->response();
}
}
13 changes: 5 additions & 8 deletions tests/Support/Format.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,14 @@

class Format extends \Jiannei\Response\Laravel\Support\Format
{
public function data(mixed $data, ?string $message, int|\BackedEnum $code, $errors = null, $from = 'success'): array
protected function formatDataFields(array $data): array
{
return [
'status' => $this->formatStatus($code),
'code' => $code,
'message' => $this->formatMessage($code, $message),
'data' => $data ?: (object) $data,
'error' => $errors ?: (object) [],
$data = parent::formatDataFields($data);

return array_merge($data, [
'extra' => [
'time' => time(),
],
];
]);
}
}
Loading

0 comments on commit 586b0dc

Please sign in to comment.