Document validation rules
Validation rules are the cornerstone of the API documentation generated by Scramble. They define the JSON schema of request parameters and contain useful information for additional parameter description.
Rule transformers
Scramble allows you to describe how validation rules should be documented using rule transformers, which transform a validation rule to a JSON schema in the documentation.
To create a rule transformer, implement the Dedoc\Scramble\Contracts\RuleTransformer interface. You must implement a few methods: shouldHandle tells if the transformer should handle a given rule, and toSchema describes how the rule is represented as JSON schema.
The toSchema method must return an instance of JSON schema and accepts the following arguments:
-
$previous– JSON schema from the previous rule (or a base one if the rule under transformation is a single rule);Rule transformers process validation rules one at a time, passing the field’s JSON schema from one transformer to another, allowing each transformer to modify a schema accordingly:
1$data = $request->validate([2'age' => ['required', 'integer', 'min:18', 'max:24'],3]);In this case, a rule transformer for the
maxrule will receive theintegerJSON schema with an already specifiedminimumvalue coming from the previousintegerandmin:18rules. -
$rule– an instance ofNormalizedRule.This is a simple wrapper around the actual validation rule, simplifying common tasks when working with rules. For example, it allows you to easily get validation rule arguments without the need to manually process rule strings: given the rule
max:255, you can check if the rule ismaxby calling$rule->is('max'), and you can get rule parameters ([255]) by calling$rule->getParameters();When using class-based rules, you can pass the name of the rule class to the
ismethod to check if the given rule is an instance of the class. -
$context– an instance ofRuleTransformerContext. It contains the additional data you may need when handling more complex rules. For example, the name of the field under validation ($context->field), the collection of all validation rules for the field ($context->fieldRules), etc.
For example, let’s add support for the ipv4 validation rule.
Here is how the rule transformer would look:
1namespace App\Documentation\RuleTransformers;2
3use Dedoc\Scramble\Contracts\RuleTransformer;4use Dedoc\Scramble\Support\Generator\Types\Type;5use Dedoc\Scramble\Support\RuleTransforming\NormalizedRule;6use Dedoc\Scramble\Support\RuleTransforming\RuleTransformerContext;7
8class Ipv4Rule implements RuleTransformer9{10 public function shouldHandle(NormalizedRule $rule): bool11 {12 return $rule->is('ipv4');13 }14
15 public function toSchema(Type $previous, NormalizedRule $rule, RuleTransformerContext $context): Type16 {17 return $previous->format('ipv4');18 }19}Next, you should register the rule transformer:
1Scramble::configure()2 ->withRuleTransformers([3 \App\Documentation\RuleTransformers\Ipv4Rule::class,4 ]);Now, when ipv4 rule is used for a field, Scramble will document it with a proper format.
All rules schemas transformers
Consider the confirmed validation rule. It requires a matching field named *_confirmed to be sent alongside the field being validated. This rule not only specifies a JSON schema, but also adds a parameter to the request.
To add support for such rules, you can implement the Dedoc\Scramble\Contracts\AllRulesSchemasTransformer interface and register a transformer like you would register a rule transformer. These transformers allow you to transform all resulting rule schemas.
For example, given the following rules, you’ll be able to transform the resulting schema bag containing name and email schemas (change schemas, add new ones, remove schemas).
1$request->validate([2 'name' => ['required', 'string'],3 'email' => ['required', 'email'],4]);Besides the already familiar shouldHandle method, you must also implement the transformAll method, in which you can modify the schema bag. This method accepts the following parameters:
$schemaBag– the schema bag being transformed, an instance ofSchemaBag.$rule– an instance ofNormalizedRule. It is described in the “Rule transformers” section above.$context– an instance ofRuleTransformerContext. It is described in the “Rule transformers” section above.
For example, here is the implementation of the confirmed rule transformer:
1use Dedoc\Scramble\Contracts\AllRulesSchemasTransformer;2use Dedoc\Scramble\Support\RuleTransforming\NormalizedRule;3use Dedoc\Scramble\Support\RuleTransforming\RuleTransformerContext;4use Dedoc\Scramble\Support\RuleTransforming\SchemaBag;5
6class ConfirmedRule implements AllRulesSchemasTransformer7{8 public function shouldHandle(NormalizedRule $rule): bool9 {10 return $rule->is('confirmed');11 }12
13 public function transformAll(SchemaBag $schemaBag, NormalizedRule $rule, RuleTransformerContext $context): void14 {15 $schemaBag->set(16 "{$context->field}_confirmation",17 clone $schemaBag->getOrFail($context->field),18 );19 }20}This can be enhanced by providing additional description to the confirmed field’s schema:
1$schema = clone $schemaBag->getOrFail($context->field);2
3$schemaBag->set(4 "{$context->field}_confirmation",5 $schema->setDescription("The value of this field must match the value of `{$context->field}`"),6);Injecting useful services
When implementing rule transformers, you can inject useful services into the transformer constructor. For example, you can use an instance of RuleSetToSchemaTransformer to transform a set of validation rules to JSON schema, or TypeTransformer to transform an instance of Scramble’s type inference system type to JSON schema:
1<?php2
3namespace App\Support\Documentation\RuleTransformers;4
5use Dedoc\Scramble\Support\Generator\TypeTransformer;6use Dedoc\Scramble\Support\RuleTransforming\RuleSetToSchemaTransformer;7
8class AwesomeRule implements RuleTransformer9{10 public function __construct(11 private RuleSetToSchemaTransformer $rulesToSchemaTransformer,12 private TypeTransformer $typeToSchemaTransformer,13 ) {}14
15 // ...16}