Skip to content

feat(openapi): Add #[ApiResponse] annotation for declarative response descriptions #143

Description

@usernane

Problem Statement

Currently, to add response descriptions to the OpenAPI spec, you must call addResponse() programmatically in the constructor. There is no declarative annotation-based approach, which is inconsistent with the rest of the annotation-driven API design (#[GetMapping], #[RequestParam], #[ResponseBody], etc.).

Proposed Solution

Add a repeatable #[ApiResponse] attribute that can be placed on service methods:

#[GetMapping]
#[ResponseBody]
#[ApiResponse(status: '200', description: 'List of products or a single product')]
#[ApiResponse(status: '404', description: 'Product not found')]
public function getProducts(): array {
    // ...
}

Implementation:

  1. Create WebFiori\Http\Annotations\ApiResponse:
#[Attribute(Attribute::TARGET_METHOD | Attribute::IS_REPEATABLE)]
class ApiResponse {
    public function __construct(
        public string $status = '200',
        public string $description = '',
    ) {}
}
  1. In WebService::toPathItemObj(), read #[ApiResponse] attributes from the mapped method and build the ResponsesObj from them instead of the default "200" => "Successful operation" fallback.

  2. If addResponse() was called programmatically, those take priority over annotations.

Alternatives Considered

  • Using doc-block annotations (rejected — framework uses PHP 8 attributes exclusively)
  • Class-level annotation (rejected — ambiguous for services with multiple HTTP methods)

Breaking Change

No

Additional Context

This came up while building the blog example for the OpenAPI/Swagger documentation post. The current workaround is calling addResponse() in the constructor, which works but breaks the declarative pattern.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions