Form Models

Resonance can map incoming data into models representing a validated data.

It is a useful abstraction that allows you to make sure you are using validated data in your application.

Usage

We will use BlogPostCreateForm as an example. It represents a request to create a blog post:

php
<?php namespace App\InputValidatedData; use Distantmagic\Resonance\InputValidatedData; readonly class BlogPostCreateForm extends InputValidatedData { public function __construct( public string $content, public string $title, ) {} }

Validators

Validators take in any data and check if it adheres to the configuration schema. The getConstraint() method must return a Constraints Schema object.

php
<?php namespace App\InputValidator; use App\InputValidatedData\BlogPostCreateForm; use Distantmagic\Resonance\Attribute\Singleton; use Distantmagic\Resonance\Constraint; use Distantmagic\Resonance\Constraint\ObjectConstraint; use Distantmagic\Resonance\Constraint\StringConstraint; use Distantmagic\Resonance\InputValidator; use Distantmagic\Resonance\SingletonCollection; /** * @extends InputValidator<BlogPostCreateForm, array{ * content: string, * title: string, * }> */ #[Singleton(collection: SingletonCollection::InputValidator)] readonly class BlogPostFormValidator extends InputValidator { public function castValidatedData(mixed $data): BlogPostCreateForm { return new BlogPostCreateForm( $data['content'], $data['title'], ); } public function getConstraint(): Constraint { return new ObjectConstraint( properties: [ 'content' => new StringConstraint(), 'title' => new StringConstraint() ], ); } }

Preferably validators should be injected somewhere by the Dependency Injection, so you don't have to set up their parameters manually. Then you can call their validateData() method.

php
<?php use Distantmagic\Resonance\InputValidatorController; use Distantmagic\Resonance\InputValidationResult; $inputValidatorController = new InputValidatorController(); /** * @var InputValidationResult $validationResult */ $validationResult = $inputValidatorController->validateData($blogPostFormValidator, [ 'content' => 'test', 'title' => 'test', ]); // If validation is successful, the errors list is empty and validation data // is set. assert($validationResult->constraintResult->getErrors()->isEmpty()); /** * It's null if validation failed. * * @var ?BlogPostCreateForm $validationResult->inputValidatedData */ assert($validationResult->inputValidatedData);

Validators do not throw an exception since invalid data is not a failure in the intended application flow. Instead, it's just a normal situation to handle.

Edit on GitHub