Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenApiSchemaProperty - Set reference to another OpenApiSchema #558

Open
marcdebus opened this issue Oct 1, 2024 · 5 comments
Open

OpenApiSchemaProperty - Set reference to another OpenApiSchema #558

marcdebus opened this issue Oct 1, 2024 · 5 comments

Comments

@marcdebus
Copy link

marcdebus commented Oct 1, 2024

Another question, or perhaps a suggestion for improvement.

Is it possible to set an OpenAPISchemaProperty as an object that references another OpenAPISchema like this?

namespace ApiPlugin\Model\DTO

#[OpenApiSchema(title: 'PersonDTO')]
class PersonDTO extends BaseDTO
{
    #[OpenApiSchemaProperty(name: 'id', type: 'integer', example: 1, description: 'The ID of person')]
    public $id;

    #[OpenApiSchemaProperty(name: 'name', type: 'string', example: 'Max', description: 'The firstname of person')]
    public $firstname;
    
    #[OpenApiSchemaProperty(name: 'name', type: 'string', example: 'Mustermann', description: 'The lastname of person')]
    public $lastname;

    #[OpenApiSchemaProperty(name: 'address', type: 'object', ref: '#/components/schemas/AddressDTO', description: 'Associated address for person')]
    public AddressDTO $address;

}

Additionally, how can I retrieve the DTOs as a schema from the ApiPlugin\Model\DTO namespace?

Below is my swagger_bake.php file.

return [
    'SwaggerBake' => [
        'prefix' => '/api/v1',
        'yml' => '/plugins/ApiPlugin/config/swagger.yml',
        'json' => '/webroot/swagger.json',
        'webPath' => '/swagger.json',
        'hotReload' => true,
        'jsonOptions' => JSON_PRETTY_PRINT,
        'requestAccepts' => [
            'application/json',
            'application/xml'
        ],
        'responseContentTypes' => [
            'application/json',
            'application/xml'
        ],
        'exceptionSchema' => 'Exception',
        'namespaces' => [
            'entities' => ['ApiPlugin\Model\DTO'],
            'tables' => []
        ]
    ]
];

  • CakePHP: 4.5.x
  • SwaggerBake Version: 2.5.9
@cnizzardini
Copy link
Owner

cnizzardini commented Oct 2, 2024

First:
I'm not certain if thats possible. Does the documentation say that is and/or does it work when you try? Not being condescending, I just go months without looking at this code now :-/ If it doesn't work, it would be a neat feature to request but I have no idea when I could get around to it :-/

Second:
DTOs have nothing to do with CakePHP entities, so I am not sure what you are trying to accomplish there. They are solely userland code that you create with no hard relation to Cake internals. So what are you actually trying to accomplish here?

@marcdebus
Copy link
Author

Sorry, I don’t want to come across as rude. I had just hoped that there was already a solution for this. I think it’s not uncommon for APIs to also represent relationships, like in this case, between a person and an address.

The OpenAPI specification provides for this, and it works as well.

relation-schema
 "components": {
        "schemas": {
            "PersonDTO": {
                "title": "PersonDTO",
                "properties": {
                    "id": {
                        "example": 1,
                        "type": "integer",
                        "description": "The ID of person"
                    },
                    "firstname": {
                        "example": "Max",
                        "type": "string",
                        "description": "The name of person"
                    },
                    "lastname": {
                        "example": "Mustermann",
                        "type": "string",
                        "description": "The lastname of person"
                    },
                    "address": {
                        "type": "object",
                        "$ref": "#/components/schemas/AddressDTO",
                        "description": "Associated address"
                    }
                },
                "type": "object"
            },
            "AddressDTO": {
                "title": "AddressDTO",
                "properties": {
                    "id": {
                        "example": 1,
                        "type": "integer",
                        "description": "The ID of address"
                    },
                    "street": {
                        "example": "Street",
                        "type": "string",
                        "description": "The street of address"
                    },
                    "houseNumber": {
                        "example": 1,
                        "type": "integer",
                        "description": "The houseNumber of address"
                    }
                },
                "type": "object"
            },
 ...

I want to use DTOs to seperate the API from the database. I know that, unfortunately, CakePHP doesn't natively support this, and most examples rely on transferring entities directly. In my opinion, this isn’t a good practice, which is why I want to introduce DTOs. Currently, my API doesn’t implement this, and when there are changes to the database, I encounter issues in other applications that consume this API.

@cnizzardini
Copy link
Owner

cnizzardini commented Oct 2, 2024

Okay yeah that makes sense, but unfortunately, you can't accomplish this as-is as the library for better and worse follows the whole CakePHP MVC design pattern. I could use this functionality as well for the same reasons you describe.

OpenApiDto is strictly built into the schema of requests/responses, so they don't really show up in the /components/schema/ OpenAPI section which really limits you here. I think the library should support what you are ultimately trying to accomplish, but its a bit of work :-/. This library would need to support registering custom schemas and it does not today.

Once it did that, at a minimum, you could get to where you want to go with the use of event listeners. If you are interested in building this in I don't think its that hard...

Something would need to be added in here https://github.com/cnizzardini/cakephp-swagger-bake/blob/2.x/src/Lib/Swagger.php#L71 that generates the custom schema. Then the config https://github.com/cnizzardini/cakephp-swagger-bake/blob/2.x/src/Lib/Configuration.php would need to support registering those custom schemas (which you were hoping it did in your initial issue post). That would really just be giving it a list of namespaces to look at.

@marcdebus
Copy link
Author

Hey, thank you for all that support.

I’ve now tried to address my requirements using Swagger-PHP, and there’s already an out-of-the-box solution available. However, this also means that a lot of manual annotations are required, which can be both a curse and a blessing. Your solution was quiet simple. :-) Thank you for that!

My first API endpoint already seems to work with DTOs, and the OpenAPI documentation is well-structured here with that relation between DTOs.

I think it’s best not to reinvent the wheel in this case.

best regards from germany

@cnizzardini
Copy link
Owner

If I were at the point where I had to annotate everything with Swagger-PHP I'd just maintain the OpenAPI YAML myself... but, do as you wish.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants