Extending OpenApi
For the OpenApi documentation we are using the zircote/swagger-php library. This library allows us to define the OpenApi documentation in PHP attributes and extend them.
Why extending OpenApi attributes
You can always use the standard attributes that are provided by the library. To reduce the amount of code duplication and make the controllers easier on the eyes we introduced custom attributes.
How to extend OpenApi attributes
With PHP 8 we can use the #[Attribute]
attribute to define custom attributes.
The easiest way is to extend an already existing attribute and add your custom logic.
These attributes can then be used in the controller itself e.g. #[CreateNoteRequestBody]
You can also use classes as a reference to describe the content as seen in the example.
Example for extending OpenApi attributes and the referenced class
<?php
declare(strict_types=1);
namespace App\Note\Attribute\Request;
use Attribute;
use OpenApi\Attributes\JsonContent;
use OpenApi\Attributes\RequestBody;
use Pimcore\Bundle\StudioBackendBundle\Note\Schema\CreateNote;
#[Attribute(Attribute::TARGET_METHOD)]
final class CreateNoteRequestBody extends RequestBody
{
public function __construct()
{
parent::__construct(
required: true,
content: new JsonContent(ref: CreateNote::class)
);
}
}
Extending Schemas
In order to extend a schema, you can use the #[Schema]
attribute and define the properties that you want to add.
The important part is to use the #[Property]
attribute to define the properties of the schema.
e.g. #[Property(description: 'title', type: 'string', example: 'Title of note')]
Schemas should be unique and are shown at the bottom of the OpenApi documentation.
Example for extending a schema
<?php
declare(strict_types=1);
namespace App\Note\Schema;
use OpenApi\Attributes\Property;
use OpenApi\Attributes\Schema;
#[Schema(
title: 'CreateNote',
required: [
'title',
'description',
'type',
],
type: 'object'
)]
final readonly class CreateNote
{
public function __construct(
#[Property(description: 'title', type: 'string', example: 'Title of note')]
private string $title,
#[Property(description: 'description', type: 'string', example: 'Description of note')]
private string $description,
#[Property(description: 'type', type: 'string', example: 'Type of note')]
private string $type
) {
}
public function getTitle(): string
{
return $this->title;
}
public function getDescription(): string
{
return $this->description;
}
public function getType(): string
{
return $this->type;
}
}