SwaggerBake Attributes

April 5, 2025 ยท View on GitHub

SwaggerBake provides some optional Attributes for enhanced functionality. It is helpful to understand the OpenApi specification when reading this documentation. Annotations exist in the following namespaces:

  • SwaggerBake\Lib\Attribute
  • SwaggerBake\Lib\Extension

Just a reminder that many usage examples exist in the SwaggerBake Demo and MixerApi Demo.

Table of Contents

AttributeUsageDescription
OpenApiDtoController ActionBuilds OpenAPI query params and request bodies from Data Transfer Objects
OpenApiFormController ActionBuilds OpenAPI for application/x-www-form-urlencoded request bodies
OpenApiHeaderController ActionCreate OpenAPI header parameters
OpenApiOperationController ActionModifies OpenAPI operation
OpenApiPaginatorController ActionCreate OpenAPI query params from CakePHP Paginator Component
OpenApiPathControllerModifies OpenAPI paths
OpenApiPathParamController ActionModify an existing OpenAPI path parameter
OpenApiQueryParamController ActionBuilds OpenAPI query param
OpenApiRequestBodyController ActionModify OpenAPI request body
OpenApiResponseController ActionModify OpenAPI response
OpenApiSchemaEntity, OpenApiDto class, or OpenApiResponse schemaModifies OpenAPI schema
OpenApiSchemaPropertyEntity, OpenApiDto class, or OpenApiResponse schemaModifies an OpenAPI schema property or defines OpenApiResponse schema
OpenApiSearchController ActionCreate OpenAPI query params from CakePHP Search plugin
OpenApiSecurityController ActionCreate/modify OpenAPI security
OpenApiDtoQueryDTO class propertyBuilds OpenAPI query param from Data Transfer Objects (deprecated, use OpenApiQueryParam in v2.2.5+)
OpenApiDtoRequestBodyDTO class propertyBuilds OpenAPI request body property from Data Transfer Objects (deprecated, use OpenApiSchemaProperty in v2.2.5+)

OpenApiDto

Method level attribute for building query parameters or request bodies from a DataTransferObject. Your DTO will need to use the OpenApiQueryParam or OpenApiSchemaProperty on its properties depending on the request type.

PropertyType / DefaultOA SpecDescription
classstringNoRequired. FQN of the DTO class.

Example DTO declaration:

#[OpenApiDto(class: ActorDto::class)]
public function index() {}

OpenApiSchemaProperty can be applied at the class or property level, example:

#[OpenApiSchemaProperty(name: "a_property")]
class ActorDto
{
    public function __construct(
        #[OpenApiSchemaProperty(name: "first_name")]
        private string $firstName
    ) {
    }
}

When your DTO is a CakePHPs Modelless Form the schema and validations are built automatically.

OpenApiForm

Method level attribute for adding form data fields. See the OpenAPI documentation on schema types for greater detail.

AttributeType / DefaultOA Spec?Description
namestringNRequired. Name of the schema property
typestring "string"YDate type such as integer, string, array etc...
format?string nullYDate format such as int32, date-time, etc...
title?string nullYTitle of the property
description?string nullYDescription of the property
examplemixed nullYAn example value
isReadOnlybool falseYIs the property read only?
isWriteOnlybool falseYIs the property write only?
isRequiredbool falseYIs the property required?
defaultmixed nullYA default value
isNullablebool falseYCan the value be null?
isDeprecatedbool falseYIs the property deprecated?
multipleOf?float nullYThe value must be a multiple of this number. For example, if 5 then accepted values are 5, 10, 15 etc.
minimum?float nullYThe minimum allowed numeric value
isExclusiveMinimumbool falseYIs the minimum value excluded from the range.
maximum?float nullYThe maximum allowed numeric value
isExclusiveMaximumbool falseYIs the maximum value excluded from the range.
minLength?integer nullYThe minimum length of a string
maxLength?integer nullYThe maximum length of a string
pattern?string nullYA regex pattern the value must follow
minItems?integer nullYThe minimum items allowed in a list
maxItems?integer nullYThe maximum items allowed in a list
hasUniqueItemsbool falseYThe list must contain unique items
minProperties?integer nullYhttp://spec.openapis.org/oas/v3.0.3#properties
maxProperties?integer nullYhttp://spec.openapis.org/oas/v3.0.3#properties
enumarray []YAn enumerated list of of options for the value

Example:

#[OpenApiForm(name: 'username', minLength: 8, maxLength: 64, pattern: '[a-zA-z]', isRequired: true)]
public function add() {}

OpenAPI:

      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                username:
                  type: string
                  minLength: 8
                  maxLength: 64
                  pattern: [a-zA-Z]
                  required: true

OpenApiHeader

Method level attribute for adding header parameters.

PropertyType / DefaultOA SpecDescription
namestring ""YName of the query parameter. Required if ref is not defined
refstring ""YAn OpenAPI $ref such as #/components/parameters/ParameterName. Required if name is not defined
typestring "string"YDate type such as integer, string, array etc...
formatstring ""YDate format such as int32, date-time, etc...
descriptionstring ""YDescription of the parameter
isRequiredbool falseYIs this parameter required?
enumarray []YAn enumerated list of accepted values
isDeprecatedbool falseYIs this parameter deprecated?
explodebool falseYhttp://spec.openapis.org/oas/v3.0.3#fixed-fields-9
stylestring ""Yhttp://spec.openapis.org/oas/v3.0.3#fixed-fields-9
examplestring, bool, or int ""YAn example value
allowEmptyValuebool falseYAre empty values allowed?

Example:

#[OpenApiHeader(name: 'X-HEAD-ATTRIBUTE', type: 'string', description: 'example')]
#[OpenApiHeader(ref: '#/x-my-project/components/parameters/my-header']
public function index() {}

OpenAPI:

     parameters:
       - name: X-HEAD-ATTRIBUTE
         in: header
         description: summary
         schema:
           type: string
       - $ref: #/x-my-project/components/parameters/my-header

OpenApiOperation

Method level attribute for OpenApi Operations.

PropertyType / DefaultOA SpecDescription
summary?string ""YesOperation summary, set to null to prevent reading from docblock
description?string ""YesOperation description, set to null to prevent reading from docblock
isVisiblebool trueNoSetting this to false will prevent the operation from appearing in OpenApi output
tagNamesarray []YesSets tag names
isDeprecatedbool falseYesIs the operation deprecated?
externalDocs?array nullYesExternal documentation
sortOrder?int nullNoThe order the operation appears at in OpenAPI output. Defaults to the order the action appears in the controller class.

Example:

#[OpenApiOperation(
    summary: 'operation title',
    description: 'a description',
    tagNames: ['Internal API', 'External API'], 
    externalDocs: [
        'url' => 'https://github.com/cnizzardini/cakephp-swagger-bake', 
        'description' => 'Check out the documentation'
    ]
)]
public function index()

OpenAPI:

    get:
      operationId: actors:index:get
      summary: operation title
      description: a description
      tags:
        - Internal API
        - External API
      externalDocs:
        url: https://github.com/cnizzardini/cakephp-swagger-bake
        description: Check out the documentation

A common use-case is to hide an operation from appearing in your OpenAPI, example:

#[OpenApiOperation(isVisible: false)]
public function index()

OpenApiPaginator

Method level attribute for adding CakePHP Paginator query parameters: page, limit, sort, and direction. OpenApiPaginator only works on index() actions.

PropertyType / DefaultOA SpecDescription
sortEnumarray []NoA list of fields that can be sorted by. This overrides the default Paginate.sortableFields
useSortTextInputboolean falseNoDisplay an input box in Swagger UI instead of a dropdown for sorting

Default usage:

#[OpenApiPaginator()]
public function index() {}

Override default sortable fields:

#[OpenApiPaginator(sortEnum: ['id', 'name'])]
public function index() {}

OpenAPI:

      parameters:
        - name: page
          in: query
          schema:
            type: integer
        - name: limit
          in: query
          schema:
            type: integer
        - name: sort
          in: query
          schema:
            type: string
            enum:
              - id
              - name
        - name: direction
          in: query
          schema:
            type: string
            enum:
              - asc
              - desc

OpenApiPath

Class level attribute to define scalar Path values.

PropertyType / DefaultOA SpecDescription
isVisibleboolean trueNoIs the path and its operations visible in OpenAPI
refstring nullYesAn OpenAPI ref such as #/paths/my-path
summarystring nullYesOverwrites the default summary (if any)
descriptionstring nullYesOverwrites the default description
tagsarray []YesSets the tags for all operations in the path. Tags set on individual operations will tak precedence.

A common use-case for this is to hide a controller from appearing in your OpenApi (the default behavior). For instance, you may have a bespoke endpoint that you don't want to publish:

#[OpenApiPath(isVisible: false)]
class UsersController extends AppController

OpenApiPathParam

Method level attribute for modifying path parameters. This is for modifying existing path parameters only. Path parameters must first be defined in your routes file.

AttributeType / DefaultOA SpecDescription
namestring ""YesName of the query parameter
refstring ""YesName of the query parameter
typestring stringYesData type
formatstring ""YesData format
descriptionstring ""YesDescription of the parameter
examplemixed ""YesAn example value
allowReservedbool falseYesAllow reserved URI characters?
isRequiredbool falseYesIs the parameter required?

Example:

#[OpenApiPathParam(name: 'id', type: 'integer', format: 'int64', description: 'ID', isRequired: true)]
public function view($id) {}

OpenAPI:

        parameters:
          - name: id
            required: true
            schema:
              description: ID
              type: integer
              format: int64

OpenApiQueryParam

Attribute for adding query parameters which can be applied as a method attribute on controller actions and a class or property attribute on DTOs.

PropertyType / DefaultOA SpecDescription
namestringYesName of the query parameter. Required if ref is empty.
refstringYesAn OpenApi $ref parameter describing the query parameter. Required if name is empty.
typestring stringYesData type. Required if name is empty.
formatstring ""Yeshttp://spec.openapis.org/oas/v3.0.3#fixed-fields-9
descriptionstring ""YesDescription of the parameter
isRequiredbool falseYIs this parameter required?
enumarray []YAn enumerated list of accepted values
isDeprecatedbool falseYesIs this parameter deprecated?
explodebool falseYeshttp://spec.openapis.org/oas/v3.0.3#fixed-fields-9
stylestring ""Yeshttp://spec.openapis.org/oas/v3.0.3#fixed-fields-9
examplestring, bool, or int ""Yeshttp://spec.openapis.org/oas/v3.0.3#fixed-fields-9
allowEmptyValuebool falseYesAllow empty values?

Example:

#[OpenApiQueryParam(name: "option", isRequired: true, enum: ["A","B","C"], description: "desc...")]
#[OpenApiQueryParam(ref: "#/x-my-project/components/parameters/my-parameter")]
public function index() {}

OpenAPI:

      parameters:
        - name: option
          in: query
          schema:
            type: string
            enum:
              - A
              - B
              - C
        - $ref: #/x-my-project/components/parameters/my-parameter

OpenApiRequestBody

Method level attribute for describing request body. Set ignoreCakeSchema for full control over request body.

AttributeType / DefaultDescription
refstring ""An optional OpenAPI $ref
descriptionstring ""Description of the request body
mimeTypesarray []An array of strings of mime types to support
requiredbool trueIs the request body required?
ignoreCakeSchemabool falseIgnore cake schema

Example:

#[OpenApiRequestBody(ref: '#/components/schema/Custom', ignoreCakeSchema: true, mimeTypes: ['application/json'])]
public function index() {}

OpenAPI:

      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schema/Custom'

OpenApiResponse

Method level attribute for controller actions defining response objects and their schema/content. The following order of operations is used to build the response:

  1. ref and schemaType take precedence.
  2. schema
  3. associations
  4. The schema inferred from CakePHP conventions.
PropertyType / DefaultOA SpecDescription
schemaTypestring "object"YThe schema response type: "object", "array" or "collection"
statusCodestring "200"YThe HTTP response code
ref?string nullYThe OpenAPI schema (e.g. "#/components/schemas/ModelName"
schema?string nullYAn FQN describing a custom response schema. The class must have either one or more #[OpenApiSchemaProperty] attribute, implement CustomSchemaInterface or both.
description?string nullYDescription of the response
mimeTypes?array nullYAn array of mime types the response can, if null settings from swagger_bake config are used.
associations?array nullNAdds associated tables to the response sample schema, see examples below.
schemaFormat?string nullYThe schema format, generally only used for schemaType of string.

Defining a multiple mimeTypes and 400-409 status code range and an expected 200 response:

#[OpenApiResponse(
    statusCode: '40x',
    ref: '#/components/schemas/Exception', 
    mimeTypes: ['application/xml','application/json']
)]
#[OpenApiResponse(schemaType: 'array', ref: '#/components/schemas/Actor')]
public function index(){}

OpenAPI:

       '200':
         content:
           application/json:
             schema:
               type: array
               items:
                 $ref: '#/components/schemas/Actor'
       '40x':
         content:
           application/xml:
             schema:
               type: object
               items:
                 $ref: '#/components/schemas/Exception'

Schema

There may be instances where your need to further customize your responses. You can provide a custom schema two ways. Both options first require you to provide an FQN to the class which describes your response schema:

#[OpenApiResponse(schema: '\App\Dto\Response\MyCustomResponse')]

Using CustomSchemaInterface:

namespace App\Dto\Response;

class MyCustomResponse implements \SwaggerBake\Lib\OpenApi\CustomSchemaInterface 
{
    /**
     * @inheritDoc
     */
    public static function getOpenApiSchema(): \SwaggerBake\Lib\OpenApi\Schema
    {
        return (new \SwaggerBake\Lib\OpenApi\Schema())  
            ->setTitle('Custom')
            ->setProperties([
                new SchemaProperty('name', 'string', null, 'Name of person', 'Paul'),
                new SchemaProperty('age', 'integer', 'int32', 'Age of person', 32)
            ]);
    }
}

Using #[OpenApiSchemaProperty]:

namespace App\Dto\Response;

#[OpenApiSchemaProperty(name: 'up_here', type: 'string', description: 'yes even up here too')]
class MyCustomResponse 
{
    #[OpenApiSchemaProperty(name: 'name', type: 'string', example: 'Paul')]
    public string $name;
    #[OpenApiSchemaProperty(name: 'age', type: 'integer', format: 'int32', example: 32)]
    public int $age;
}

SwaggerBake will convert these into an OpenApi response schema for you. Note, you can use both the interface and attributes in your response class. Attributes take precedence over the Schema returned from getOpenApiSchema(). By default, schema will not be added to #/components/schemas and so will not appear in SwaggerUI's schema list. You can add the #[OpenApiSchema] attribute to your schema class to change the default behavior.

Associations

The association property allows you to include associations defined in your Table class within your OpenAPI response sample schema. To not include associations:

#[OpenApiResponse(associations: false)]

To include all immediately associated tables (depth of one):

#[OpenApiResponse(associations: [])]

To include deeper associations or restrict the associations, use the whiteList option. This supports dot notation:

#[OpenApiResponse(associations: ['whiteList' => ['Films.Languages', 'City']])]

Remember schemaType defaults to object. We can specify array if we are returning many records:

#[OpenApiResponse(associations: [], schemaType: 'array')]

Since the base table is inferred using CakePHP naming conventions we can change the base table if necessary:

#[OpenApiResponse(associations: ['table' => 'OtherTable'])]

OpenApiSchema

Class level attribute for modifying OpenAPI Schema.

PropertyType / DefaultOA SpecDescription
visibilityint 1NoDetermines the visibility of the schema, see OpenApiSchema class constants
title?string nullYesOverwrites the default title
description?string nullYesOverwrites the default description (if any)

Visibility

You can use the constants below when defining visibility:

NameValueDescription
OpenApiSchema::VISIBLE_DEFAULT1Default behavior. Adds the schema to #/components/schema/{SchemaName} if it matches a controller with a RESTful route.
OpenApiSchema::VISIBLE_ALWAYS2Always add the schema to #/components/schema/{SchemaName}.
OpenApiSchema::VISIBLE_HIDDEN3Never add the schema to #/components/schema/{SchemaName} and instead adds it to #/x-swagger-bake/components/schema/{SchemaName}. This hides the schema from the Swagger UIs Schemas section, but still allows the schema to be used for request and response bodies.
OpenApiSchema::VISIBLE_NEVER4Never add the schema anywhere. Warning this can break request body definitions and response samples.

Example:

#[OpenApiSchema(visbility: OpenApiSchema::VISIBLE_ALWAYS, title: 'Always visible schema')]
class Actor extends Entity{}

OpenApiSchemaProperty

Class or property level attribute for customizing Schema properties. Note that the attribute does not have to exist in your entity. You can add adhoc attributes as needed and optionally combine with Virtual Fields.

AttributeType / DefaultOA Spec?Description
namestringNRequired. Name of the schema property
typestring "string"YDate type such as integer, string, array etc...
format?string nullYDate format such as int32, date-time, etc...
title?string nullYTitle of the property
description?string nullYDescription of the property
examplemixed nullYAn example value
isReadOnlybool falseYIs the property read only?
isWriteOnlybool falseYIs the property write only?
isRequiredbool falseYIs the property required?
defaultmixed nullYA default value
isNullablebool falseYCan the value be null?
isDeprecatedbool falseYIs the property deprecated?
multipleOf?float nullYThe value must be a multiple of this number. For example, if 5 then accepted values are 5, 10, 15 etc.
minimum?float nullYThe minimum allowed numeric value
isExclusiveMinimumbool falseYIs the minimum value excluded from the range.
maximum?float nullYThe maximum allowed numeric value
isExclusiveMaximumbool falseYIs the maximum value excluded from the range.
minLength?int nullYThe minimum length of a string
maxLength?int nullYThe maximum length of a string
pattern?string nullYA regex pattern the value must follow
minItems?int nullYThe minimum items allowed in a list
maxItems?int nullYThe maximum items allowed in a list
hasUniqueItemsbool falseYThe list must contain unique items
minProperties?int nullYhttp://spec.openapis.org/oas/v3.0.3#properties
maxProperties?int nullYhttp://spec.openapis.org/oas/v3.0.3#properties
enumarray []YAn enumerated list of of options for the value
itemsarray []YFor use with array schema properties.
#[OpenApiSchemaProperty(name: 'example_one', minLength: 5, maxLength: 10)]
#[OpenApiSchemaProperty(name: 'example_two', minLength: 5, enum: ['PG','R'], isRequired: true)]
#[OpenApiSchemaProperty(name: 'example_virtual_field', isReadOnly: true)]
class Employee extends Entity {

OpenAPI:

        example_one:
          type: string
          minLength: 5
          maxLength: 10
        example_two:
          type: string
          enum:
            - PG
            - R
          required: true
        example_virtual_field:
          type: string
          readOnly: true

OpenApiSearch

Method level attribute for documenting search parameters using the popular friendsofcake/search plugin.

AttributeType / DefaultDescription
aliasstringRequired. The table alias to be used by TableLocator::get($alias)
collectionstring defaultThe Cake Search collection (see documentation])
optionsarray []Optional array to be passed into TableLocator::get($alias, $options)
#[OpenApiSearch(alias: 'Films')]
public function index()
{
    $this->request->allowMethod('get');
    $query = $this->Films
        ->find('search', [
            'search' => $this->request->getQueryParams(),
            'collection' => 'default'
        ])
        ->contain(['Languages']);
    $films = $this->paginate($query);

    $this->set(compact('films'));
    $this->viewBuilder()->setOption('serialize', 'films');
}

Friends Of Cake Search Filter:

<?php
declare(strict_types=1);

namespace App\Model\Filter;

use Search\Model\Filter\FilterCollection;

class FilmsCollection extends FilterCollection
{
    public function initialize(): void
    {
        $this
            ->add('title', 'Search.Like', [
                'before' => true,
                'after' => true,
                'mode' => 'or',
                'comparison' => 'LIKE',
                'wildcardAny' => '*',
                'wildcardOne' => '?',
                'fields' => ['title'],
            ])
            ->add('rating', 'Search.Value', [
                'before' => true,
                'after' => true,
                'mode' => 'or',
                'wildcardAny' => '*',
                'wildcardOne' => '?',
                'fields' => ['rating'],
            ]);
    }

OpenAPI:

      parameters:
        - name: title
          in: query
          description: Like title
          schema:
            type: string
        - name: rating
          in: query
          description: Value rating
          schema:
            type: string

OpenApiSecurity

Method level attribute for documenting security requirements on an Operation. See the main documentation for more information. You may define multiple.

PropertyType / DefaultOA SpecDescription
namestringYesRequired. Name of the security option
scopesarray []YesSecurity Scopes

Here is an example of documenting that an index endpoint requires BearerAuth security with read scope. The name should match what is defined in your YAML Security Scheme Object.

#[OpenApiSecurity(name: 'BearerAuth', scopes: ['read'])]
#[OpenApiSecurity(name: 'ApiKey')]
public function index(){}