mmae/apiresponse 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

mmae/apiresponse

Composer 安装命令:

composer require mmae/apiresponse

包简介

Standard API Response for Front-End Clients

README 文档

README

Standard JSON API response envelope for Laravel apps. Every response — success or failure — comes back in the same shape, so front-end clients parse one format.

Install

composer require mmae/apiresponse

Service provider auto-registers via package discovery (MMAE\ApiResponse\MMAEApiResponseServiceProvider).

Response envelope

{
  "success": true,
  "data": {},
  "errors": {},
  "message": "",
  "token": ""
}

HasApiResponse trait

MMAE\ApiResponse\Traits\HasApiResponse — add to any controller (or class) that needs to emit the envelope.

use MMAE\ApiResponse\Traits\HasApiResponse;

class UserController extends Controller
{
    use HasApiResponse;

    public function show(User $user)
    {
        return $this->successResponse(UserResource::make($user));
    }
}

Methods (all private, all return JsonResponse):

Method Purpose Status default
successResponse($data, $statusCode = 200) success + data 200
successResponseWithToken($data, $token, $message = '', $statusCode = 200) success + data + token (e.g. login) 200
successMessageResponse($message, $statusCode = 200) success + message only, no data 200
createdResponse($data, $message = '', $statusCode = 201) success + data, resource created 201
registeredSuccessfullyResponse($data, $token, $message = '', $statusCode = 201) success + data + token, user registered 201
updatedResponse($data, $message = '', $statusCode = 200) success + data, resource updated 200
deletedResponse($message = '', $statusCode = 200) success + message only, resource deleted, no data 200
failedResponse($errors, $message, $statusCode = null) failure + errors Response::$FAILED_STATUS (400)
failedMessageResponse($message, $statusCode = null) failure + message only Response::$FAILED_STATUS (400)

$data accepts array, Collection, JsonResource, LengthAwarePaginator, or Model. All methods funnel through the private makeResponse().

See examples/UserController.md for a full CRUD + registration controller with real captured responses for every scenario (success, validation failure, not found, unhandled/broken code — app.debug on and off).

Debugging: dumpAndDie()

HasApiResponse::dumpAndDie(JsonResponse $response) — private helper, pretty-prints a JsonResponse envelope to stdout and halts execution (exit). API-only: no HTML VarDumper output, just the JSON. Not currently called by any of the public response methods above — invoke it directly on a built response when you need to inspect the exact envelope during development.

Rendering exceptions: exceptionResponse() and per-exception builders

HasApiResponse::exceptionResponse(Throwable $exception, ?Request $request = null): JsonResponse — renders any caught Throwable into the envelope. Exceptions implementing MMAE\ApiResponse\Contracts\ExceptionContract (the 4 exceptions below) render themselves; anything else is wrapped in GeneralErrorException (original preserved as $previous, subject to the debug mode rules) and reported to the app's exception handler via report(). $request defaults to the current request when omitted.

public function show(string $id)
{
    try {
        return $this->successResponse(UserResource::make(User::findOrFail($id)));
    } catch (Throwable $e) {
        return $this->exceptionResponse($e);
    }
}

Only the fallback GeneralErrorException path is reported — ModelNotFoundException, RouteNotFoundException, ValidationException, and any custom ExceptionContract exception are expected/known conditions and aren't logged.

One dedicated builder method per envelope exception is also available — construct and render directly without throw/catch:

Method Builds
generalErrorExceptionResponse($request, ?$message, $statusCode = 500, ?$previous) GeneralErrorException
modelNotFoundExceptionResponse($request, ?$message, $statusCode = 404) ModelNotFoundException
routeNotFoundExceptionResponse($request, ?$message, $statusCode = 404) RouteNotFoundException
validationExceptionResponse($request, $errors, ?$message, $statusCode = 422) ValidationException
public function show(Request $request, string $id)
{
    $user = User::find($id);

    if (! $user) {
        return $this->modelNotFoundExceptionResponse($request);
    }

    return $this->successResponse(UserResource::make($user));
}

Debug traces: withDebugTrace()

HasApiResponse::withDebugTrace(JsonResponse $response, Throwable $source): JsonResponse — protected helper, appends a debug block (exception, file, line, trace) to an already-built envelope response. Frame args are stripped from the trace (may carry sensitive values like passwords/tokens). Used internally by the 4 envelope exceptions (ValidationException, ModelNotFoundException, RouteNotFoundException, GeneralErrorException) when rendering with a $previous exception and app.debug is true — see Debug mode: raw message + trace below. Can also be called directly if you build custom exception rendering.

ApiRequest

MMAE\ApiResponse\Request\ApiRequestFormRequest base class. Overrides failedValidation() to return failedResponse() (422) instead of Laravel's default redirect.

use MMAE\ApiResponse\Request\ApiRequest;

class StoreUserRequest extends ApiRequest
{
    public function authorize(): bool
    {
        return true;
    }

    public function rules(): array
    {
        return [
            'email' => ['required', 'email'],
        ];
    }
}

Override defaults per-request by declaring properties:

class StoreUserRequest extends ApiRequest
{
    protected ?string $message = 'Please fix the errors below';
    protected ?int $statusCode = 422;
    // ...
}

Config defaults

MMAE\ApiResponse\Configurations\Response — static properties, override directly if needed:

  • $VALIDATION_FAILED_STATUS = 422
  • $FAILED_STATUS = 400
  • $VALIDATION_FAILED_MESSAGE = nullnull uses the translated apiresponse::messages.validation_failed line; set a string to override.

Static props, not config-file-backed. Set them once app boots (e.g. AppServiceProvider::boot()) to change defaults app-wide:

use MMAE\ApiResponse\Configurations\Response;

public function boot(): void
{
    Response::$FAILED_STATUS = 422;
    Response::$VALIDATION_FAILED_MESSAGE = 'The given data was invalid.';
}

Affects failedResponse() / failedMessageResponse() (via $FAILED_STATUS) and ApiRequest::failedValidation() (via $VALIDATION_FAILED_STATUS / $VALIDATION_FAILED_MESSAGE) whenever caller doesn't pass explicit $statusCode/$message.

Exceptions

MMAE\ApiResponse\Exceptions\* — throwable exceptions that render themselves as the standard envelope. Each implements MMAE\ApiResponse\Contracts\ExceptionContract (render(Request): JsonResponse), so throwing one anywhere in the app produces the envelope automatically — no extra wiring required. See Rendering exceptions above for the HasApiResponse helpers that build/render these directly.

Exception Signature Default status Default message key
ValidationException (array|Collection $errors, ?string $message = null, int $statusCode = 422, ?Throwable $previous = null) 422 apiresponse::messages.validation_failed
ModelNotFoundException (?string $message = null, int $statusCode = 404, ?Throwable $previous = null) 404 apiresponse::messages.resource_not_found
RouteNotFoundException (?string $message = null, int $statusCode = 404, ?Throwable $previous = null) 404 apiresponse::messages.route_not_found
GeneralErrorException (?string $message = null, int $statusCode = 500, ?Throwable $previous = null) 500 apiresponse::messages.something_went_wrong

Pass null (or omit) $message to use the translated default; pass a string to override it for that instance — an explicit message always wins, regardless of app.debug. Messages are resolved at render() time, using whichever locale is active when the response is built — not the locale at throw time.

Mapping Laravel's own exceptions

Response::handleExceptions(Exceptions $exceptions) maps Laravel's built-in exceptions to the matching envelope exception, for JSON requests only (non-JSON requests fall through to Laravel's default handling). Wire it in bootstrap/app.php:

use MMAE\ApiResponse\Configurations\Response;

->withExceptions(function (Exceptions $exceptions) {
    Response::handleExceptions($exceptions);
})

Handles: Illuminate\Validation\ValidationException, Illuminate\Database\Eloquent\ModelNotFoundException, unmatched routes (NotFoundHttpException), and any other Throwable as a GeneralErrorException.

Debug mode: raw message + trace

When an envelope exception is auto-constructed from a real caught exception (i.e. via Response::handleExceptions, which always passes the original as $previous), render() behaves differently based on config('app.debug'):

  • app.debug = truemessage is the original exception's raw getMessage(), and a debug block is added to the envelope: { "exception": "...", "file": "...", "line": ..., "trace": [...] }. Frame args are stripped from every trace entry (they can carry sensitive values like passwords or tokens).
  • app.debug = falsemessage is the translated default (or your override), and no debug key is present at all.

This only applies to exceptions carrying a $previous (i.e. mapped by handleExceptions). If you throw one of these exceptions directly in app code with an explicit $message, that message is shown as-is regardless of app.debug — it's an intentional, developer-authored message, not something to hide.

Unrecognized throwables passed to exceptionResponse() are also reported to the app's exception handler via report() before being wrapped — see Rendering exceptions above.

Translations

Default messages are translated via apiresponse::messages.* (English + Arabic shipped). Laravel resolves the active locale automatically; override a locale's strings by publishing:

php artisan vendor:publish --tag=apiresponse-lang

This copies the lang files to lang/vendor/apiresponse/{locale}/messages.php in the host app, where they take priority over the package's own.

Artisan command

php artisan make:request-api {name}

Generates a request class extending ApiRequest into App\Http\Requests\Api, using src/stubs/request.stub.

Testing & tooling

Package tests live in src/tests (Testbench, not top-level tests/), written in Pest. src/tests/Pest.php binds TestCase to Unit/Feature.

composer test        # vendor/bin/pest --test-directory=src/tests
composer analyse     # vendor/bin/phpstan analyse (level: max, via larastan)
composer format      # vendor/bin/pint
composer refactor    # vendor/bin/rector process (src/, PHP 8.4 + Laravel 13 rule sets)

phpstan.neon.dist and rector.php both scope to src/ (skip src/stubs and src/tests).

mmae/apiresponse 适用场景与选型建议

mmae/apiresponse 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 195 次下载、GitHub Stars 达 1, 最近一次更新时间为 2024 年 07 月 29 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 mmae/apiresponse 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 mmae/apiresponse 我们能提供哪些服务?
定制开发 / 二次开发

基于 mmae/apiresponse 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 195
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 21
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-07-29