Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Normalize and standardize Laravel API response data structures. - 规范化和标准化 Laravel API 响应数据结构。

License

NotificationsYou must be signed in to change notification settings

guanguans/laravel-api-response

Normalize and standardize Laravel API response data structures. - 规范化和标准化 Laravel API 响应数据结构。

testscheck & fix stylingcodecovLatest Stable VersionGitHub release (with filter)Total DownloadsLicense

Features

  • Support for customized response data structure
  • Support for restful API response(optional)
  • Support for automatically handled api exception
  • Support for localized message
  • Support for customized pipe(Process api response structure through pipeline)
  • Support for customized exception pipe(Convert exception to api response through pipeline)

Requirement

  • PHP >= 8.0

Installation

composer require guanguans/laravel-api-response --ansi -v

Configuration

Publish files(optional)

php artisan vendor:publish --provider="Guanguans\\LaravelApiResponse\\ServiceProvider" --ansi -v

Usage

Quick start

<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Support\Traits\ApiResponseFactory;useIlluminate\Http\JsonResponse;useSymfony\Component\HttpKernel\Exception\HttpException;class Controllerextends \App\Http\Controllers\Controller{use ApiResponseFactory;publicfunctionexamples():JsonResponse    {// return $this->apiResponse()->error($message);// return $this->apiResponse()->badRequest($message);// return $this->apiResponse()->unauthorized($message);// return $this->apiResponse()->exception($exception);// throw new \RuntimeException('This is a runtime exception.');// throw new HttpException(400);// return $this->apiResponse()->success($data);// return $this->apiResponse()->noContent($message);// ...return$this->apiResponse()->ok();    }}

Default response structure

{"status":"boolean","code":"integer","message":"string","data":"mixed","error":"array<string, mixed>"}

Default response examples

model
<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Support\Traits\ApiResponseFactory;useGuanguans\LaravelApiResponse\Tests\Laravel\Models\User;useIlluminate\Http\JsonResponse;class Controllerextends \App\Http\Controllers\Controller{use ApiResponseFactory;publicfunctionexample():JsonResponse    {$user = User::query()->with(['country','posts'])->first();return$this->apiResponse()->success($user);    }}
{"status":true,"code":200,"message":"OK","data": {"id":1,"name":"John","country_id":1,"created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01","country": {"id":1,"name":"China","created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01"        },"posts": [            {"id":1,"title":"PHP is the best language!","user_id":1,"created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01"            },            {"id":2,"title":"JAVA is the best language!","user_id":1,"created_at":"2024-01-01 00:00:02","updated_at":"2024-01-01 00:00:02"            },            {"id":3,"title":"Python is the best language!","user_id":1,"created_at":"2024-01-01 00:00:03","updated_at":"2024-01-01 00:00:03"            }        ]    },"error": {}}
eloquent collection
<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Support\Traits\ApiResponseFactory;useGuanguans\LaravelApiResponse\Tests\Laravel\Models\User;useIlluminate\Http\JsonResponse;class Controllerextends \App\Http\Controllers\Controller{use ApiResponseFactory;publicfunctionexample():JsonResponse    {$users = User::query()->with(['country','posts'])->get();return$this->apiResponse()->success($users);    }}
{"status":true,"code":200,"message":"OK","data": [        {"id":1,"name":"John","country_id":1,"created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01","country": {"id":1,"name":"China","created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01"            },"posts": [                {"id":1,"title":"PHP is the best language!","user_id":1,"created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01"                },                {"id":2,"title":"JAVA is the best language!","user_id":1,"created_at":"2024-01-01 00:00:02","updated_at":"2024-01-01 00:00:02"                },                {"id":3,"title":"Python is the best language!","user_id":1,"created_at":"2024-01-01 00:00:03","updated_at":"2024-01-01 00:00:03"                }            ]        },        {"id":2,"name":"Tom","country_id":2,"created_at":"2024-01-01 00:00:02","updated_at":"2024-01-01 00:00:02","country": {"id":2,"name":"USA","created_at":"2024-01-01 00:00:02","updated_at":"2024-01-01 00:00:02"            },"posts": [                {"id":4,"title":"Go is the best language!","user_id":2,"created_at":"2024-01-01 00:00:04","updated_at":"2024-01-01 00:00:04"                },                {"id":5,"title":"JavaScript is the best language!","user_id":2,"created_at":"2024-01-01 00:00:05","updated_at":"2024-01-01 00:00:05"                },                {"id":6,"title":"Ruby is the best language!","user_id":2,"created_at":"2024-01-01 00:00:06","updated_at":"2024-01-01 00:00:06"                }            ]        },        {"id":3,"name":"Jerry","country_id":3,"created_at":"2024-01-01 00:00:03","updated_at":"2024-01-01 00:00:03","country": {"id":3,"name":"Japan","created_at":"2024-01-01 00:00:03","updated_at":"2024-01-01 00:00:03"            },"posts": [                {"id":7,"title":"C is the best language!","user_id":3,"created_at":"2024-01-01 00:00:07","updated_at":"2024-01-01 00:00:07"                }            ]        },        {"id":4,"name":"Jack","country_id":4,"created_at":"2024-01-01 00:00:04","updated_at":"2024-01-01 00:00:04","country": {"id":4,"name":"Korea","created_at":"2024-01-01 00:00:04","updated_at":"2024-01-01 00:00:04"            },"posts": []        },        {"id":5,"name":"Rose","country_id":5,"created_at":"2024-01-01 00:00:05","updated_at":"2024-01-01 00:00:05","country": {"id":5,"name":"UK","created_at":"2024-01-01 00:00:05","updated_at":"2024-01-01 00:00:05"            },"posts": []        },        {"id":6,"name":"Lucy","country_id":6,"created_at":"2024-01-01 00:00:06","updated_at":"2024-01-01 00:00:06","country": {"id":6,"name":"France","created_at":"2024-01-01 00:00:06","updated_at":"2024-01-01 00:00:06"            },"posts": []        },        {"id":7,"name":"Lily","country_id":7,"created_at":"2024-01-01 00:00:07","updated_at":"2024-01-01 00:00:07","country": {"id":7,"name":"Germany","created_at":"2024-01-01 00:00:07","updated_at":"2024-01-01 00:00:07"            },"posts": []        }    ],"error": {}}
simple paginate
<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Support\Traits\ApiResponseFactory;useGuanguans\LaravelApiResponse\Tests\Laravel\Models\User;useIlluminate\Http\JsonResponse;class Controllerextends \App\Http\Controllers\Controller{use ApiResponseFactory;publicfunctionexample():JsonResponse    {$simplePaginate = User::query()->with(['country','posts'])->simplePaginate(3);return$this->apiResponse()->success($simplePaginate);    }}
{"status":true,"code":200,"message":"OK","data": {"data": [            {"id":1,"name":"John","country_id":1,"created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01","country": {"id":1,"name":"China","created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01"                },"posts": [                    {"id":1,"title":"PHP is the best language!","user_id":1,"created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01"                    },                    {"id":2,"title":"JAVA is the best language!","user_id":1,"created_at":"2024-01-01 00:00:02","updated_at":"2024-01-01 00:00:02"                    },                    {"id":3,"title":"Python is the best language!","user_id":1,"created_at":"2024-01-01 00:00:03","updated_at":"2024-01-01 00:00:03"                    }                ]            },            {"id":2,"name":"Tom","country_id":2,"created_at":"2024-01-01 00:00:02","updated_at":"2024-01-01 00:00:02","country": {"id":2,"name":"USA","created_at":"2024-01-01 00:00:02","updated_at":"2024-01-01 00:00:02"                },"posts": [                    {"id":4,"title":"Go is the best language!","user_id":2,"created_at":"2024-01-01 00:00:04","updated_at":"2024-01-01 00:00:04"                    },                    {"id":5,"title":"JavaScript is the best language!","user_id":2,"created_at":"2024-01-01 00:00:05","updated_at":"2024-01-01 00:00:05"                    },                    {"id":6,"title":"Ruby is the best language!","user_id":2,"created_at":"2024-01-01 00:00:06","updated_at":"2024-01-01 00:00:06"                    }                ]            },            {"id":3,"name":"Jerry","country_id":3,"created_at":"2024-01-01 00:00:03","updated_at":"2024-01-01 00:00:03","country": {"id":3,"name":"Japan","created_at":"2024-01-01 00:00:03","updated_at":"2024-01-01 00:00:03"                },"posts": [                    {"id":7,"title":"C is the best language!","user_id":3,"created_at":"2024-01-01 00:00:07","updated_at":"2024-01-01 00:00:07"                    }                ]            }        ],"links": {"first":"http:\/\/localhost?page=1","last":null,"prev":null,"next":"http:\/\/localhost?page=2"        },"meta": {"current_page":1,"from":1,"path":"http:\/\/localhost","per_page":3,"to":3        }    },"error": {}}
resource
<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Support\Traits\ApiResponseFactory;useGuanguans\LaravelApiResponse\Tests\Laravel\Models\User;useGuanguans\LaravelApiResponse\Tests\Laravel\Resources\UserResource;useIlluminate\Http\JsonResponse;class Controllerextends \App\Http\Controllers\Controller{use ApiResponseFactory;publicfunctionexample():JsonResponse    {$userResource = UserResource::make(User::query()->with(['country','posts'])->first());return$this->apiResponse()->success($userResource);    }}
{"status":true,"code":200,"message":"OK","data": {"id":1,"name":"John","country_id":1,"created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01","country": {"id":1,"name":"China","created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01"        },"posts": [            {"id":1,"title":"PHP is the best language!","user_id":1,"created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01"            },            {"id":2,"title":"JAVA is the best language!","user_id":1,"created_at":"2024-01-01 00:00:02","updated_at":"2024-01-01 00:00:02"            },            {"id":3,"title":"Python is the best language!","user_id":1,"created_at":"2024-01-01 00:00:03","updated_at":"2024-01-01 00:00:03"            }        ]    },"error": {}}
resource collection
<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Support\Traits\ApiResponseFactory;useGuanguans\LaravelApiResponse\Tests\Laravel\Models\User;useGuanguans\LaravelApiResponse\Tests\Laravel\Resources\UserCollection;useIlluminate\Http\JsonResponse;class Controllerextends \App\Http\Controllers\Controller{use ApiResponseFactory;publicfunctionexample():JsonResponse    {$userCollection = UserCollection::make(User::query()->with(['country','posts'])->get());return$this->apiResponse()->success($userCollection);    }}
{"status":true,"code":200,"message":"OK","data": [        {"id":1,"name":"John","country_id":1,"created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01","country": {"id":1,"name":"China","created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01"            },"posts": [                {"id":1,"title":"PHP is the best language!","user_id":1,"created_at":"2024-01-01 00:00:01","updated_at":"2024-01-01 00:00:01"                },                {"id":2,"title":"JAVA is the best language!","user_id":1,"created_at":"2024-01-01 00:00:02","updated_at":"2024-01-01 00:00:02"                },                {"id":3,"title":"Python is the best language!","user_id":1,"created_at":"2024-01-01 00:00:03","updated_at":"2024-01-01 00:00:03"                }            ]        },        {"id":2,"name":"Tom","country_id":2,"created_at":"2024-01-01 00:00:02","updated_at":"2024-01-01 00:00:02","country": {"id":2,"name":"USA","created_at":"2024-01-01 00:00:02","updated_at":"2024-01-01 00:00:02"            },"posts": [                {"id":4,"title":"Go is the best language!","user_id":2,"created_at":"2024-01-01 00:00:04","updated_at":"2024-01-01 00:00:04"                },                {"id":5,"title":"JavaScript is the best language!","user_id":2,"created_at":"2024-01-01 00:00:05","updated_at":"2024-01-01 00:00:05"                },                {"id":6,"title":"Ruby is the best language!","user_id":2,"created_at":"2024-01-01 00:00:06","updated_at":"2024-01-01 00:00:06"                }            ]        },        {"id":3,"name":"Jerry","country_id":3,"created_at":"2024-01-01 00:00:03","updated_at":"2024-01-01 00:00:03","country": {"id":3,"name":"Japan","created_at":"2024-01-01 00:00:03","updated_at":"2024-01-01 00:00:03"            },"posts": [                {"id":7,"title":"C is the best language!","user_id":3,"created_at":"2024-01-01 00:00:07","updated_at":"2024-01-01 00:00:07"                }            ]        },        {"id":4,"name":"Jack","country_id":4,"created_at":"2024-01-01 00:00:04","updated_at":"2024-01-01 00:00:04","country": {"id":4,"name":"Korea","created_at":"2024-01-01 00:00:04","updated_at":"2024-01-01 00:00:04"            },"posts": []        },        {"id":5,"name":"Rose","country_id":5,"created_at":"2024-01-01 00:00:05","updated_at":"2024-01-01 00:00:05","country": {"id":5,"name":"UK","created_at":"2024-01-01 00:00:05","updated_at":"2024-01-01 00:00:05"            },"posts": []        },        {"id":6,"name":"Lucy","country_id":6,"created_at":"2024-01-01 00:00:06","updated_at":"2024-01-01 00:00:06","country": {"id":6,"name":"France","created_at":"2024-01-01 00:00:06","updated_at":"2024-01-01 00:00:06"            },"posts": []        },        {"id":7,"name":"Lily","country_id":7,"created_at":"2024-01-01 00:00:07","updated_at":"2024-01-01 00:00:07","country": {"id":7,"name":"Germany","created_at":"2024-01-01 00:00:07","updated_at":"2024-01-01 00:00:07"            },"posts": []        }    ],"error": {}}
error
<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Support\Traits\ApiResponseFactory;useIlluminate\Http\JsonResponse;class Controllerextends \App\Http\Controllers\Controller{use ApiResponseFactory;publicfunctionexample():JsonResponse    {return$this->apiResponse()->error('This is an error.');    }}
{"status":false,"code":400,"message":"This is an error.","data":null,"error": {}}
exception
<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Support\Traits\ApiResponseFactory;useIlluminate\Http\JsonResponse;class Controllerextends \App\Http\Controllers\Controller{use ApiResponseFactory;publicfunctionexample():JsonResponse    {config()->set('app.debug',false);$runtimeException =new \RuntimeException('This is a runtime exception.');return$this->apiResponse()->exception($runtimeException);    }}
{"status":false,"code":500,"message":"Internal Server Error","data":null,"error": {"message":"Internal Server Error"    }}
debug exception
<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Support\Traits\ApiResponseFactory;useIlluminate\Http\JsonResponse;class Controllerextends \App\Http\Controllers\Controller{use ApiResponseFactory;publicfunctionexample():JsonResponse    {config()->set('app.debug',true);$runtimeException =new \RuntimeException('This is a runtime exception.');return$this->apiResponse()->exception($runtimeException);    }}
{"status":false,"code":500,"message":"This is a runtime exception.","data":null,"error": {"message":"This is a runtime exception.","exception":"RuntimeException","file":"\/tests\/Feature\/ExceptionDataTypesTest.php","line":45,"trace": [            {"function":"{closure}","class":"P\\Tests\\Feature\\ExceptionDataTypesTest","type":"->"            },            {"file":"\/vendor\/pestphp\/pest\/src\/Factories\/TestCaseFactory.php","line":151,"function":"call_user_func"            },            {"function":"Pest\\Factories\\{closure}","class":"P\\Tests\\Feature\\ExceptionDataTypesTest","type":"->"            },            {"file":"\/vendor\/pestphp\/pest\/src\/Concerns\/Testable.php","line":301,"function":"call_user_func_array"            },            {"file":"\/vendor\/pestphp\/pest\/src\/Support\/ExceptionTrace.php","line":29,"function":"Pest\\Concerns\\{closure}","class":"P\\Tests\\Feature\\ExceptionDataTypesTest","type":"->"            },            {"file":"\/vendor\/pestphp\/pest\/src\/Concerns\/Testable.php","line":302,"function":"ensure","class":"Pest\\Support\\ExceptionTrace","type":"::"            },            {"file":"\/vendor\/pestphp\/pest\/src\/Concerns\/Testable.php","line":278,"function":"__callClosure","class":"P\\Tests\\Feature\\ExceptionDataTypesTest","type":"->"            },            {"file":"\/vendor\/phpunit\/phpunit\/src\/Framework\/TestCase.php","line":1617,"function":"__test","class":"P\\Tests\\Feature\\ExceptionDataTypesTest","type":"->"            },            {"file":"\/vendor\/phpunit\/phpunit\/src\/Framework\/TestCase.php","line":1223,"function":"runTest","class":"PHPUnit\\Framework\\TestCase","type":"->"            },            {"file":"\/vendor\/phpunit\/phpunit\/src\/Framework\/TestResult.php","line":729,"function":"runBare","class":"PHPUnit\\Framework\\TestCase","type":"->"            },            {"file":"\/vendor\/phpunit\/phpunit\/src\/Framework\/TestCase.php","line":973,"function":"run","class":"PHPUnit\\Framework\\TestResult","type":"->"            },            {"file":"\/vendor\/phpunit\/phpunit\/src\/Framework\/TestSuite.php","line":685,"function":"run","class":"PHPUnit\\Framework\\TestCase","type":"->"            },            {"file":"\/vendor\/phpunit\/phpunit\/src\/Framework\/TestSuite.php","line":685,"function":"run","class":"PHPUnit\\Framework\\TestSuite","type":"->"            },            {"file":"\/vendor\/phpunit\/phpunit\/src\/TextUI\/TestRunner.php","line":651,"function":"run","class":"PHPUnit\\Framework\\TestSuite","type":"->"            },            {"file":"\/vendor\/phpunit\/phpunit\/src\/TextUI\/Command.php","line":146,"function":"run","class":"PHPUnit\\TextUI\\TestRunner","type":"->"            },            {"file":"\/vendor\/pestphp\/pest\/src\/Console\/Command.php","line":119,"function":"run","class":"PHPUnit\\TextUI\\Command","type":"->"            },            {"file":"\/vendor\/pestphp\/pest\/bin\/pest","line":61,"function":"run","class":"Pest\\Console\\Command","type":"->"            },            {"file":"\/vendor\/pestphp\/pest\/bin\/pest","line":62,"function":"{closure}"            },            {"file":"\/vendor\/bin\/pest","line":115,"function":"include"            }        ]    }}
exception handler
<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Middleware\SetJsonAcceptHeader;useIlluminate\Http\JsonResponse;class Controllerextends \App\Http\Controllers\Controller{publicfunction__construct()    {$this->middleware(SetJsonAcceptHeader::class)->only('example');    }publicfunctionexample():JsonResponse    {config()->set('app.debug',false);thrownew \RuntimeException('This is a runtime exception.');    }}
{"status":false,"code":500,"message":"Internal Server Error","data":null,"error": {"message":"Internal Server Error"    }}
locale exception
<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Support\Traits\ApiResponseFactory;useIlluminate\Http\JsonResponse;class Controllerextends \App\Http\Controllers\Controller{use ApiResponseFactory;publicfunctionexample():JsonResponse    {config()->set('app.debug',false);config()->set('app.locale','zh_CN');$runtimeException =new \RuntimeException('This is a runtime exception.');return$this->apiResponse()->exception($runtimeException);    }}

resources/lang/zh_CN.json

{"...":"...","Unauthenticated.":"未认证。","This is a runtime exception.":"这是一个运行时异常。"}
{"status":false,"code":500,"message":"这是一个运行时异常。","data":null,"error": {"message":"这是一个运行时异常。"    }}
more examples...

FAQ

How to get [\Guanguans\LaravelApiResponse\ApiResponse] instance
<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Contracts\ApiResponseContract;useGuanguans\LaravelApiResponse\Facades\ApiResponseFacade;useGuanguans\LaravelApiResponse\Support\Traits\ApiResponseFactory;useIlluminate\Http\JsonResponse;class Controllerextends \App\Http\Controllers\Controller{use ApiResponseFactory;publicfunctiongetInstance():JsonResponse    {/** @var \Guanguans\LaravelApiResponse\ApiResponse $apiResponse */// $apiResponse = ApiResponseFacade::getFacadeRoot();// $apiResponse = resolve(ApiResponseContract::class);// $apiResponse = app(ApiResponseContract::class);$apiResponse =$this->apiResponse();return$apiResponse->ok();    }}
How to specify api paths to automatically handle exception
How to always respond with successful http status code
  • Reference to theStatusCodePipe.php
  • Remove the configurationapi-response.pipes.StatusCodePipe
How to localize message
  • Reference to theMessagePipe.php
  • Add localize status code message [installLaravel-Lang/http-statusescomposer require --dev laravel-lang/http-statuses or create lang filesresources/lang/***/http-statuses.php]
  • Add localize message [create lang json filesresources/lang/***.json]
How to customize pipe
  • Reference to thePipes
  • Simple example:
<?phpstaticfunction (array$structure,\Closure$next):JsonResponse {if ($structure['data']instanceof \Traversable) {$structure['data'] =iterator_to_array($structure['data']);    }return$next($structure);};
How to customize exception pipe
How to operate pipe dynamically in a single api
<?phpnamespaceApp\Http\Controllers\Api;useGuanguans\LaravelApiResponse\Support\Traits\ApiResponseFactory;useIlluminate\Http\JsonResponse;class Controllerextends \App\Http\Controllers\Controller{use ApiResponseFactory;publicfunctionexample():JsonResponse    {return$this            ->apiResponse()// ->unshiftPipes(...$pipes)// ->pushPipes(...$pipes)// ->beforePipes($findPipe, ...$pipes)// ->afterPipes($findPipe, ...$pipes)// ->removePipes(...$findPipes)// ->extendPipes($callback)// ->tapPipes($callback)            ->success($data);    }}
Shortcut methods of http status
All methods

Testing

composertest

Changelog

Please seeCHANGELOG for more information on what has changed recently.

Contributing

Please seeCONTRIBUTING for details.

Security Vulnerabilities

Please reviewour security policy on how to report security vulnerabilities.

Credits

Thanks

License

The MIT License (MIT). Please seeLicense File for more information.

About

Normalize and standardize Laravel API response data structures. - 规范化和标准化 Laravel API 响应数据结构。

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

    Packages

    No packages published

    Contributors3

    •  
    •  
    •  

    Languages


    [8]ページ先頭

    ©2009-2025 Movatter.jp