You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Laravel后端生成TypeScript类型?实践困惑求解

问题:Laravel API返回消息在OpenAPI文档中的复用方案

我正在研究如何从Laravel应用的API生成TypeScript类型,目前用Scribe生成API文档,再基于该文档生成TypeScript类型。但遇到一个问题:服务器返回的消息需要包含在OpenAPI文档中,按当前方案,每个端点都必须使用专属Resource并手动放入服务器消息,否则API文档无法包含该消息。

示例代码如下:

控制器方法

/**
 * @apiResource App\Http\Admin\Resources\PermissionCreateResource
 * @apiResourceModel App\Models\Permission
 * @param PermissionCreateRequest $request
 */
public function create(PermissionCreateRequest $request): JsonResponse
{
    $input = $request->validated();
    $permission = $this->permissionFactory->createPermission($input);
    return new JsonResponse(new PermissionCreateResource($permission), Response::HTTP_CREATED);
}

对应的PermissionCreateResource

public function toArray(Request $request): array
{
    return [
        'message' => 'Permission created',
        'data' => [
            'id' => $this->id,
            'name' => $this->name,
        ]
    ];
}

解决方案

方案1:封装通用基础Resource类

创建一个基础Resource类,统一处理message和data的结构,其他业务Resource继承该类,避免重复编写消息结构,同时让Scribe能识别统一的响应格式。

// app/Http/Resources/BaseResource.php
class BaseResource extends JsonResource
{
    protected string $message;

    public function __construct($resource, string $message)
    {
        parent::__construct($resource);
        $this->message = $message;
    }

    public function toArray(Request $request): array
    {
        return [
            'message' => $this->message,
            'data' => parent::toArray($request),
        ];
    }
}

业务Resource继承后只需定义data字段:

// app/Http/Admin/Resources/PermissionCreateResource.php
class PermissionCreateResource extends BaseResource
{
    public function toArray(Request $request): array
    {
        return parent::toArray($request) + [
            'data' => [
                'id' => $this->id,
                'name' => $this->name,
            ]
        ];
    }
}

控制器调用时传入消息:

return new JsonResponse(new PermissionCreateResource($permission, 'Permission created'), Response::HTTP_CREATED);

方案2:用Scribe的@apiResponse注解定义通用结构

如果不想修改Resource层级,可以直接在控制器注释中用@apiResponse手动声明包含message的响应格式,复用通用Resource即可。

/**
 * @apiResourceModel App\Models\Permission
 * @apiResponse {
 *  "message": "string",
 *  "data": {
 *      "id": "integer",
 *      "name": "string"
 *  }
 * } 201 "Permission created"
 * @param PermissionCreateRequest $request
 */
public function create(PermissionCreateRequest $request): JsonResponse
{
    $input = $request->validated();
    $permission = $this->permissionFactory->createPermission($input);
    return response()->json([
        'message' => 'Permission created',
        'data' => new PermissionResource($permission)
    ], Response::HTTP_CREATED);
}

方案3:Laravel响应宏统一返回格式

在AppServiceProvider中定义响应宏,让所有API返回遵循统一格式,再配置Scribe识别该结构。

// app/Providers/AppServiceProvider.php
use Illuminate\Support\Facades\Response;

public function boot()
{
    Response::macro('apiSuccess', function ($data, string $message = '操作成功', int $statusCode = 200) {
        return response()->json([
            'message' => $message,
            'data' => $data,
        ], $statusCode);
    });
}

控制器中使用:

return response()->apiSuccess(new PermissionResource($permission), 'Permission created', Response::HTTP_CREATED);

之后可以通过Scribe的@apiResponse注解或自定义解析器,让OpenAPI文档自动包含message字段的定义。


内容的提问来源于stack exchange,提问作者Maarduk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 13:35:15