The goal of swagger-php is to generate a swagger.json using phpdoc annotations.
To output:
{
"swagger": "2.0",
"schemes": ["http"],
"host": "example.com",
"basePath": "/api"
}
Write:
/**
* @SWG\Swagger(
* schemes={"http"},
* host="example.com",
* basePath="/api"
* )
*/
Note that Doctrine annotation supports arrays, but uses {
and }
instead of [
and ]
.
And although doctrine also supports objects, but also uses {
and }
and requires the property names to be surrounded with "
.
DON'T write:
/**
* @SWG\Swagger(
* info={
* "title"="My first swagger documented API",
* "version"="1.0.0"
* }
* )
*/
But use the annotation with the same name as the property, such as @SWG\Info
for info
:
/**
* @SWG\Swagger(
* @SWG\Info(
* title="My first swagger documented API",
* version="1.0.0"
* )
* )
*/
This adds validation, so when you misspell a property or forget a required property it will trigger a php warning.
For example if you'd write titel="My first ...
swagger-php whould generate a notice with "Unexpected field "titel" for @SWG\Info(), expecting "title", ..."
You can use constants inside doctrine annotations.
define("API_HOST", ($env === "production") ? "example.com" : "localhost");
/**
* @SWG\Swagger(host=API_HOST)
*/
When you're using the CLI you'll need to include the php file with the constants using the --bootstrap
options:
$ swagger --bootstrap constants.php
You shouldn't place all annotations inside one big @SWG\Swagger() annotation block, but scatter them throughout your codebase. swagger-php will scan your project and merge all annotations into one @SWG\Swagger annotation.
The big benefit swagger-php provides is that the documentation lives close to the code implementing the api.
Placing multiple annotations of the same type will result in an array of objects.
For objects, the convention for properties, is to use the same field name as the annotation: response
in a @SWG\Response
, property
in a @SWG\Property
, etc.
/**
* @SWG\Get(
* path="/products",
* summary="list products",
* @SWG\Response(
* response=200,
* description="A list with products"
* ),
* @SWG\Response(
* response="default",
* description="an ""unexpected"" error"
* )
* )
*/
Generates:
{
"swagger": "2.0",
"paths": {
"/products": {
"get": {
"summary": "list products",
"responses": {
"200": {
"description": "A list with products"
},
"default": {
"description": "an \"unexpected\" error"
}
}
}
}
},
"definitions": []
}
swagger-php looks at the context of the comment which reduces duplication.
/**
* @SWG\Definition()
*/
class Product {
/**
* The product name
* @var string
* @SWG\Property()
*/
public $name;
}
results in:
{
"swagger": "2.0",
"definitions": {
"Product": {
"properties": {
"name": {
"type": "string",
"description": "The product name"
}
}
}
}
}
As if you'd written:
/**
* The product name
* @var string
*
* @SWG\Property(
* property="name",
* type="string",
* description="The product name"
* )
*/
public $name;
It's common that multiple requests have some overlap in either the request or the response.
The spec solves most of this by using $ref
s
/**
* @SWG\Definition(
* definition="product_id",
* type="integer",
* format="int64",
* description="The unique identifier of a product in our catalog"
* )
*/
Results in:
{
"swagger": "2.0",
"paths": {},
"definitions": {
"product_id": {
"description": "The unique identifier of a product in our catalog",
"type": "integer",
"format": "int64"
}
}
}
Which doesn't do anything by itself but now you can reference this piece by its path in the json #/definitions/product_id
/**
* @SWG\Property(ref="#/definitions/product_id")
*/
public $id;
For more tips on refs, browse through the using-refs example.
Alternatively, you can extend the definition altering specific fields using the $
in-place of the #
/**
* @SWG\Property(
* ref="$/definitions/product_id",
* format="int32"
* )
*/
public $id;
For extensions tips and examples, browse through using-dynamic-refs example.
The specification allows for custom properties as long as they start with "x-" therefor all swagger-php annotations have an x
property which will unfold into "x-" properties.
/**
* @SWG\Info(
* title="Example",
* version=1,
* x={
* "some-name": "a-value",
* "another": 2,
* "complex-type": {
* "supported":{
* {"version": "1.0", "level": "baseapi"},
* {"version": "2.1", "level": "fullapi"},
* }
* }
* }
* )
*/
Results in:
"info": {
"title": "Example",
"version": 1,
"x-some-name": "a-value",
"x-another": 2,
"x-complex-type": {
"supported": [{
"version": "1.0",
"level": "baseapi"
}, {
"version": "2.1",
"level": "fullapi"
}]
}
},
The Amazon API Gateway for example, makes use of these.
To see which output maps to which annotation checkout swagger-explained Which also contain snippets of the swagger specification