A delightfully tasty tool for generating Swagger documentation with OpenApi 3.0.0 schema. This plugin automatically builds your Swagger UI and ReDoc from your existing cake models and routes.
- Creates OpenApi paths and operations from your RESTful routes and controllers.
- Creates OpenAPI Schema from your Entities and Tables.
- Integrates with: Paginator, friendsofcake/search, Authentication, Validator, and Bake.
- Provides additional functionality through Annotations and Doc Blocks.
Demo Site | Demo Code | Screenshot
- Installation
- Setup
- Getting Started
- Automatic Documentation
- Doc Blocks
- Annotations
- Events
- Customizing Exception Responses
- Extending Views and Controllers
- Generating OpenAPI
- Multiple Instances of SwaggerBake
- Debug Commands
- Bake Theme
- ...
SwaggerBake requires CakePHP4 and a few dependencies that will be automatically installed via composer.
composer require cnizzardini/cakephp-swagger-bake
Run bin/cake plugin load SwaggerBake
or manually load the plugin:
# src/Application.php
public function bootstrap(): void
{
// other logic...
$this->addPlugin('SwaggerBake');
}
For standard applications that have not split their API into plugins, the automated setup should work. Otherwise use the manual setup.
Run bin/cake swagger install
and then add a route.
-
Create a base swagger.yml file in
config\swagger.yml
. An example file is provided here. -
Create a
config/swagger_bake.php
file. See the example file here for further explanation. Then just add a route.
Create a route for the SwaggerUI page in config/routes.php
, example:
$builder->connect('/my-swagger-ui', ['controller' => 'Swagger', 'action' => 'index', 'plugin' => 'SwaggerBake']);
-
You can generate OpenAPI json from the command line at anytime with
bin/cake swagger bake
. -
If Hot Reload is enabled (see config) OpenAPI will be generated each time you browse to SwaggerUI (or Redoc) in your web browser.
-
Checkout the debug commands for troubleshooting and the bake theme for generating RESTful controllers.
I built this library to reduce the need for annotations to build documentation. SwaggerBake will automatically build the following from your existing routes and models without additional effort:
- Paths
- Resource (route)
- Operations
- Summary and description
- GET, POST, PATCH, DELETE
- Form fields and JSON using your Cake models
- Responses
- Sub resources
- Security/Authentication
- Schema
See details for how CakePHP conventions are interpreted into OpenAPI 3.0 schema.
SwaggerBake works with your existing YML definitions and will not overwrite anything.
SwaggerBake will parse your DocBlocks for information. The
first line reads as the Operation Summary and the second as the Operation Description, @see
, @deprecated
, and
@throws
are also supported. Throw tags use the Exception classes HTTP status code. For instance, a
MethodNotAllowedException
displays as a 405 response in Swagger UI, while a standard PHP Exception displays as a 500
code. You must use the FQN for exceptions.
/**
* Swagger Operation Summary
*
* This displays as the operations long description
*
* @see https://book.cakephp.org/4/en/index.html The link and this description appear in Swagger
* @deprecated
* @throws \Cake\Http\Exception\BadRequestException An optional bad request description here
* @throws \Exception
*/
public function index() {}
For Entities, the description from @property
is supported:
/**
* City Entity
*
* @property string $name Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
* incididunt ut labore et dolore magna aliqua.
*
* - some
* - bullets
*
* Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore
* magna aliqua.
*/
SwaggerBake provides some optional Annotations for enhanced functionality. These can be imported individually from
SwaggerBake\Lib\Annotation
or set to an alias such as Swag
: use SwaggerBake\Lib\Annotation as Swag
.
Read the Annotations docs for detailed examples.
Annotation | Description |
---|---|
@SwagPaginator | Supports CakePHP Paginator Component |
@SwagSearch | Supports Friends of Cake Search |
@SwagQuery | Adds query parameters |
@SwagForm | Adds form parameters |
@SwagDto | Adds Data Transfer Objects (DTOs) |
@SwagHeader | Adds header parameters |
@SwagPathParameter | Modifies path parameters |
@SwagSecurity | Adds/modifies authentication. Read below |
@SwagOperation | Modifies OpenAPI operations (can be used to hide operations) |
@SwagRequestBody | Describes OpenAPI request body |
@SwagRequestBodyContent | Describes OpenAPI request body content |
@SwagResponseSchema | Describes OpenAPI response schema |
@SwagPath | Describes OpenAPI paths (can be used to hide paths) |
@SwagEntity | Describes OpenAPI Entity (can be used to hide entity schemas) |
@SwagEntityAttribute | Add/modify OpenAPI schema properties |
SwaggerBake comes with an event system to allow for further control over your OpenAPI schema.
Event | Description |
---|---|
SwaggerBake.Operation.created | Dispatched each time an OpenAPI Path > Operation is created |
SwaggerBake.Schema.created | Dispatched each time an OpenAPI Schema is created |
SwaggerBake.initialize | Dispatched during initialization phase on SwaggerBake |
SwaggerBake.beforeRender | Dispatched before SwaggerBake outputs OpenAPI JSON |
By default, SwaggerBake uses components > schemas > Exception as your Swagger documentations Exception schema. See the
default swagger.yml and exceptionSchema
in swagger_bake.php for more
info.
You can provide custom schemas for exceptions by adding schema to your YAML at
#/x-swagger-bake/components/schemas/app-exceptions
and referencing the FQN of the exception with x-exception-fqn
,
example:
x-swagger-bake:
components:
schemas:
app-exceptions:
ValidationException:
x-exception-fqn: '\MixerApi\ExceptionRender\ValidationException'
type: object
properties:
exception:
type: string
example: ValidationException
message:
type: string
example: Error saving resource `Schema`
url:
type: string
example: /url/path
code:
type: integer
example: 500
violations:
type: array
items:
$ref: '#/x-swagger-bake/components/schemas/app-exceptions/Violation'
It's possible to write extensions for SwaggerBake. Read the extensions documentation. There are several other options to extend functionality documented below:
You may use your own swagger install in lieu of the version that comes with SwaggerBake. Simply don't add a custom route as indicated in the installation steps. In this case just reference the generated swagger.json within your userland Swagger UI install.
You might want to perform some additional logic (checking for authentication) before rendering the built-in Swagger UI. This is easy to do. Just create your own route and controller, then reference the built-in layout and template:
// config/routes.php
$builder->connect('/my-swagger-docs', ['controller' => 'MySwagger', 'action' => 'index']);
To get started, copy SwaggerController into your project.
You will need to use your own controller (see above). From there you can copy the layouts and templates into your project and inform your controller action to use them instead. Checkout out the CakePHP documentation on Views for specifics. This can be useful if you'd like to add additional functionality to SwaggerUI (or Redoc) using their APIs or if your project is not installed in your web servers document root (i.e. a sub-folder).
There a three options for generating swagger.json:
-
Call
swagger bake
which can be included as part of your build process. -
Enable the
hotReload
option in config/swagger_bake.php (recommended for local development only). -
Call SwaggerBake programmatically:
$swagger = (new \SwaggerBake\Lib\Factory\SwaggerFactory())->create();
$swagger->getArray(); # returns swagger array
$swagger->toString(); # returns swagger json
$swagger->writeFile('/full/path/to/your/swagger.json'); # writes swagger.json
If your application has multiple APIs that are split into plugins you can generate unique OpenAPI schema, Swagger UI,
and Redoc for each plugin. Setup a new swagger_bake.php
and swagger.yaml
in plugins/OtherApi/config
. These
configurations should point to your plugins paths and namespaces. Next, create a custom
SwaggerController and load the configuration within initialize()
:
public function initialize(): void
{
parent::initialize();
Configure::load('OtherApi.swagger_bake', 'default', false); // note: `false` for the third argument is important
$this->loadComponent('SwaggerBake.SwaggerUi');
}
When running bin/cake swagger bake
you will need to specify your plugins swagger_bake config:
bin/cake swagger bake --config OtherApi.swagger_bake
In addition to swagger bake
these console helpers provide insight into how your Swagger documentation is generated.
Displays a list of routes that can be viewed in Swagger.
bin/cake swagger routes
Displays a list of models that can be viewed in Swagger.
bin/cake swagger models
SwaggerBake comes with Bake templates for scaffolding RESTful controllers compatible with SwaggerBake and OpenAPI 3.0 schema. Using the bake theme is completely optional, but will save you some time since the default bake theme is not specifically designed for RESTful APIs.
bin/cake bake controller {Name} --theme SwaggerBake
OpenAPI Schema Support Roadmap
- Swagger uses your existing swagger.yml as a base for adding additional paths and schema.
- Generates JSON based on the OpenAPI 3 specification. I am still working on implementing the full spec.
- All Schemas and Paths generated must have the following in your CakePHP Application:
- App\Model\Entity class (for schemas only)
- App\Controller class
- Must be a valid route
- Three versions of schema will be created:
- Default with all properties
#/components/schemas/Entity
- Writeable properties
#/x-swagger-bake/components/schemas/Entity-Write
- Readable properties
#/x-swagger-bake/components/schemas/Entity-Read
- Default with all properties
- Entity Attributes:
- Reads descriptions from
@property
doc block tags. - Hidden attributes will not be visible.
- Primary Keys will be set to read only by default.
- DateTime fields named
created
andmodified
are automatically set to read only per Cake convention.
- Reads descriptions from
- CRUD Responses
- Index, Edit, Add, and View methods default to an HTTP 200 with the Controllers related Cake Entity schema.
- Delete defaults to HTTP 204 (no content).
- Table Validators:
- Reads in Validator rules such as requirePresence, minLength, maxLength, basic math comparison operators, regex, inList, hasAtLeast, and hasAtMost.
- Security Scheme
- Leverages the CakePHP AuthenticationComponent
- Will automatically set security on operations if a single securityScheme
is defined in your swagger.yaml. If more than one security schema exists you will need to use
@SwagSecurity
. @SwagSecurity
takes precedence.
- SwaggerBake supports the following formats: application/json, application/x-www-form-urlencoded, application/xml, application/hal+json, and application/ld+json
SwaggerBake does not document schema associations. If your application includes associations on things like
GET requests, you can easily add them into your swagger documentation through the OpenAPI allOf
property. Since
SwaggerBake works in conjunction with OpenAPI YAML you can easily add a new schema with this association. Below is an
example of extending an existing City schema to include a Country association.
# in your swagger.yml
components:
schemas:
CityExtended:
description: 'City with extended information including Country'
type: object
allOf:
- $ref: '#/components/schemas/City'
- type: object
properties:
country:
$ref: '#/components/schemas/Country'
Then in your controller action you'd specify the Schema:
/**
* View method
* @Swag\SwagResponseSchema(refEntity="#/components/schemas/CityExtended")
*/
public function view($id)
{
$this->request->allowMethod('get');
$city = $this->Cities->get($id, ['contain' => ['Countries']]);
$this->set(compact('cities'));
$this->viewBuilder()->setOption('serialize', 'cities');
}
The demo application includes this and many other examples of usage. Read more about oneOf
, anyOf
, allOf
, and
not
in the OpenAPI 3 documentation.
This is built for CakePHP 4.x only. A cake-3.8 option is available, but not supported.
Version | Cake Version | Supported | Unit Tests | Notes |
---|---|---|---|---|
1.* | 4.* | Yes | Yes | Currently supported |
cake-3.8 | 3.8.* | No | Yes | See branch cake-3.8. Completely untested and unsupported |
No API definition provided.
Verify that swagger.json exists.
Unable to create swagger file. Try creating an empty file first or checking permissions
Create the swagger.json manually matching the path in your config/swagger_bake.php
file.
Output file is not writable
Change permissions on your swagger.json file
, 764
should do.
Controller not found
Make sure a controller actually exists for the route resource.
By default Cake RESTful resources will only create routes for index, view, add, edit and delete. You can add and remove paths using CakePHPs route resource functionality. Read the Cake Routing documentation which describes in detail how to add, remove, modify, and alter routes.
Either disable CSRF protection on your main route in config/routes.php
or enable CSRF protection in Swagger
UI. The library does not currently support adding this in for you.
Make sure the route is properly defined in your config/routes.php
file.
This is a new library so please take some steps before reporting issues. You can copy & paste the JSON SwaggerBake outputs into https://editor.swagger.io/ which will automatically convert the JSON into YML and display potential schema issues.
Please included the following in your issues a long with a brief description:
- Steps to Reproduce
- Actual Outcome
- Expected Outcome
Feature requests are welcomed.
Send pull requests to help improve this library. You can include SwaggerBake in your primary Cake project as a local source to make developing easier:
-
Make a fork of this repository and clone it to your localhost
-
Remove
cnizzardini\cakephp-swagger-bake
from yourcomposer.json
-
Add a paths repository to your
composer.json
"minimum-stability": "dev",
"repositories": [
{
"type": "path",
"url": "/absolute/local-path-to/cakephp-swagger-bake",
"options": {
"symlink": true
}
}
]
- Run
composer require cnizzardini/cakephp-swagger-bake @dev
Undo these steps when you're done. Read the full composer documentation on loading from path here: https://getcomposer.org/doc/05-repositories.md#path
# unit tests only
composer test
# unit tests and static analysis
composer analyze