GithubHelp home page GithubHelp logo

laravel-data-scramble's Introduction

laravel-data-scramble

Support for OpenAPI schema conversion of Spatie's Laravel Data DTOs for Scramble

๐Ÿšจ Mostly uploaded as a code sample; I am not planning to make a package out of it since it's small and very purpose-specific, but I thought it would be an example of what you can do with Scramble's extension API.

If you are someone who uses Laravel Data as a way of creating very type-safe code, though, feel free to grab a sample!

How it works

You must first register the extensions with Scramble by adding their FQDNs to the scramble.extensions config:

// scramble.php
return [
    'extensions' => [
        LaravelDataRequestExtension::class,
        LaravelDataToSchema::class,
    ]
];

Then, you can use Laravel Data in the form of request or response schemas through type-hinting on your controller method signatures (as a parameter or return type).

How it (internally) works

The CastsDtoToSchema trait features the code that converts the DTO into a Schema instance Scramble can understand. We can easily do this by leveraging Scramble's RulesToParameters helper and Laravel Data's validation capabilities.

We use these capabilities to create an OperationExtension that allows us to detect DTOs and register them as possible "request bodies" of an OpenAPI operation. Then, we register a TypeToSchemaExtension to further indicate how to handle controller methods that return DTOs to Scramble. Both handlers execute the same logic.

Here is a step-by-step breakdown of how it works:

  • We use the Reflection API to get the FQDN of the DTO and pass it to the schemaFromDto method
  • Then, we use the Reflection API to create an instance of the DTO without constructor arguments to avoid validation issues
  • We tell Laravel Data to get us a list of validation rules that Laravel understands
  • image
  • We then pass these resulting rules to Scramble's RulesToParameters service, which in turn returns an array of Scramble Parameters
  • image
  • Lastly, we use the Schema::createFromParameters method to generate the request body Schema that we then add to our Operation
  • image

A slightly different process is done for requests that accept query parameters. Instead of converting our Parameters into a Schema, we simply add them to the request using the addParameters method of the Operation object.

DTOs with DataCollections

Laravel Data will not return a traditional validation rule payload for all levels of the DTO if you have any DataCollection props. Instead, it will return NestedRule instances, which Scramble's RulesToParameters helper cannot understand.

Using the reflection API, I wrote a small recursion program to analyze the NestedRule. NestedRule executes a Closure fed to it when the validation rule payload is being created, and it invokes that Closure when it's time to validate the property with the NestedRule.

You can statically analyze the Closure by using reflections to get the value of the protected NestedRule closure property and then using ReflectionClosure to get a reflection of the Closure itself.

Then, we grab the context of the Closure by accessing its use variables through getUseVariables. This will give us access to the DataProperty that represents our DataCollection, which we can then use to get its registered attributes, namely #[DataCollectionOf(...)]. We can then grab the first parameter passed to DataCollectionOf, which is the FQDN of the DTO that will be inside the DataCollection.

image

With an instance of our DTO now available, we repeat the initial rule conversion process described earlier in this file, with additional logic necessary to correct the key names.

Then, we replace our NestedRule with these values, and re-run the logic recursively until no NestedRule instances are left.

image

laravel-data-scramble's People

Contributors

cristianhg2 avatar

Stargazers

Igor Moraes avatar  avatar Felipe Valencia avatar

Watchers

 avatar Igor Moraes avatar

laravel-data-scramble's Issues

Not analyze laravel-data as response object

Hi,
I found you example and it works very well, but I'm not able to make it work in a response object.
I have an api that get a laravel-data object as the request params and the docs works very well. Then, the api returns anothere laravel-data object in the response. Since the response is a little bit complex, I have to annotate the response in the phpdoc and your code seems to work, but when it tries to get validation rule using reflectionClass, it returns always an empty array... what can I do?

And another point: how can i get also the description of the field (eg. using a comment on the variable)?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.