1. Go to this page and download the library: Download cuyz/valinor-bundle library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
use CuyZ\Valinor\Mapper\TreeMapper;
final class SomeAutowiredService
{
public function __construct(
private TreeMapper $mapper,
) {}
public function someMethod(): void
{
$this->mapper->map(SomeDto::class, /* … */);
// …
}
}
// config/services.php
use CuyZ\Valinor\Mapper\TreeMapper;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $container): void {
$container
->services()
->set(\Acme\SomeService::class)
->args([
service(TreeMapper::class),
]);
};
use CuyZ\Valinor\Mapper\MapperBuilder;
final class SomeAutowiredService
{
public function __construct(
private MapperBuilder $mapperBuilder,
) {}
public function someMethod(): void
{
$this->mapperBuilder
// …
// Some mapper configuration
// …
->mapper()
->map(SomeDto::class, /* … */);
// …
}
}
use CuyZ\Valinor\Normalizer\JsonNormalizer;
final class SomeAutowiredService
{
public function __construct(
private JsonNormalizer $jsonNormalizer,
) {}
public function someMethod(): void
{
// …
$this->jsonNormalizer->normalize($someObject);
// …
}
}
// config/services.php
use CuyZ\Valinor\Normalizer\JsonNormalizer;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $container): void {
$container
->services()
->set(\Acme\SomeService::class)
->args([
service(JsonNormalizer::class),
]);
};
use CuyZ\Valinor\Normalizer\Format;
use CuyZ\Valinor\NormalizerBuilder;
final class SomeAutowiredService
{
public function __construct(
private NormalizerBuilder $normalizerBuilder,
) {}
public function someMethod(): void
{
$this->normalizerBuilder
// …
// Some normalizer configuration
// …
->normalizer(Format::array())
->normalize($someValue);
// …
}
}
// config/packages/valinor.php
return static function (Symfony\Config\ValinorConfig $config): void {
// Date formats that will be supported by the mapper by default.
$config->mapper()->dateFormatsSupported(['Y-m-d', 'Y-m-d H:i:s']);
// For security reasons, exceptions thrown in a constructor will not be
// caught by the mapper unless they are specifically allowed by giving their
// class names to the configuration below.
$config->mapper()->allowedExceptions([
\Webmozart\Assert\InvalidArgumentException::class,
\App\CustomException::class,
]);
// When enabled, controllers using `#[MapRequest]` can type-hint a PSR-7
// `ServerRequestInterface` parameter instead of Symfony's `Request`. The
// bundle will automatically handle the conversion.
//
// Note that this ache()->envWhereFilesAreWatched(['dev', 'custom_env']);
};
use CuyZ\ValinorBundle\Http\MapRequest;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Attribute\Route;
#[AsController]
final class ListArticles
{
/**
* GET /api/authors/{authorId}/articles?status=X&page=X&limit=X
*
* @param positive-int $page
* @param int<10, 100> $limit
*/
#[Route('/api/authors/{authorId}/articles', methods: 'GET')]
#[MapRequest]
public function __invoke(
string $authorId,
string $status,
int $page = 1,
int $limit = 10,
): Response { /* … */ }
}
use CuyZ\Valinor\Mapper\Http\FromQuery;
use CuyZ\Valinor\Mapper\Http\FromRoute;
use CuyZ\ValinorBundle\Http\MapRequest;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Attribute\Route;
#[AsController]
final class ListArticles
{
/**
* GET /api/authors/{authorId}/articles?status=X&page=X&limit=X
*
* @param positive-int $page
* @param int<10, 100> $limit
*/
#[Route('/api/authors/{authorId}/articles', methods: 'GET')]
#[MapRequest]
public function __invoke(
// Can only be mapped from the route
#[FromRoute] string $authorId,
// Can only be mapped from query parameters
#[FromQuery] string $status,
#[FromQuery] int $page = 1,
#[FromQuery] int $limit = 10,
): Response { /* … */ }
}
use CuyZ\Valinor\Mapper\Configurator\ConvertKeysToCamelCase;
use CuyZ\Valinor\Mapper\Http\FromBody;
use CuyZ\ValinorBundle\Http\MapRequest;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Attribute\Route;
#[AsController]
final class CreateAuthor
{
#[Route('/api/authors/new', methods: 'POST')]
#[MapRequest(new ConvertKeysToCamelCase())]
public function __invoke(
#[FromBody] string $name,
#[FromBody] DateTimeInterface $birthDate,
): Response { /* … */ }
}
use Attribute;
use CuyZ\Valinor\Mapper\Configurator\ConvertKeysToCamelCase;
use CuyZ\Valinor\Mapper\Configurator\RestrictKeysToSnakeCase;
use CuyZ\Valinor\MapperBuilder;
use CuyZ\ValinorBundle\Http\MapRequestAttribute;
#[Attribute(Attribute::TARGET_METHOD)]
final class MyAppMapRequest implements MapRequestAttribute
{
public function __construct(
/** @var list<non-empty-string> */
private array $dateFormats = ['Y-m-d', 'Y-m-d H:i:s'],
private bool $allowScalarValueCasting = false,
) {}
public function configureMapperBuilder(MapperBuilder $builder): MapperBuilder
{
// Always restrict keys to `snake_case`
$builder = $builder->configureWith(new RestrictKeysToSnakeCase());
// Always convert keys to `camelCase`
$builder = $builder->configureWith(new ConvertKeysToCamelCase());
$builder = $builder->supportDateFormats(...$this->dateFormats);
if ($this->allowScalarValueCasting) {
$builder = $builder->allowScalarValueCasting();
}
return $builder;
}
}
use CuyZ\Valinor\Mapper\Http\FromBody;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Attribute\Route;
#[AsController]
final class CreateComment
{
#[Route('/api/comments', methods: 'POST')]
#[MyAppMapRequest(dateFormats: ['d/m/Y'], allowScalarValueCasting: true)]
public function __invoke(
#[FromBody] string $author,
#[FromBody] string $content,
): Response { /* … */ }
}
use CuyZ\Valinor\Mapper\Http\FromQuery;
use CuyZ\Valinor\Mapper\Http\FromRoute;
use CuyZ\ValinorBundle\Http\MapRequest;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Attribute\Route;
final readonly class ArticleFilters
{
public function __construct(
public string $status,
/** @var positive-int */
public int $page = 1,
/** @var int<10, 100> */
public int $limit = 10,
) {}
}
#[AsController]
final class ListArticles
{
/**
* GET /api/authors/{authorId}/articles?status=X&page=X&limit=X
*/
#[Route('/api/authors/{authorId}/articles', methods: 'GET')]
#[MapRequest]
public function __invoke(
#[FromRoute] string $authorId,
#[FromQuery(asRoot: true)] ArticleFilters $filters,
): Response { /* … */ }
}
use CuyZ\Valinor\Mapper\Http\FromRoute;
use CuyZ\ValinorBundle\Http\MapRequest;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Attribute\AsController;
use Symfony\Component\Routing\Attribute\Route;
#[AsController]
final class ListArticles
{
#[Route('/api/authors/{authorId}/articles', methods: 'GET')]
#[MapRequest]
public function __invoke(
// Request object injected automatically
Request $request,
#[FromRoute] string $authorId,
): Response {
if ($request->headers->has('My-Customer-Header')) {
// …
}
}
}
use CuyZ\Valinor\Mapper\Configurator\MapperBuilderConfigurator;
use CuyZ\Valinor\MapperBuilder;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
#[AutoconfigureTag('valinor.mapper_builder_configurator.default')]
final class DefaultMapperConfigurator implements MapperBuilderConfigurator
{
public function __construct(
/** @var non-empty-list<non-empty-string> */
private array $dateFormats,
) {}
public function configureMapperBuilder(MapperBuilder $builder): MapperBuilder
{
return $builder->supportDateFormats(...$this->dateFormats);
}
}
use CuyZ\Valinor\Normalizer\Configurator\NormalizerBuilderConfigurator;
use CuyZ\Valinor\NormalizerBuilder;
use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag;
#[AutoconfigureTag('valinor.normalizer_builder_configurator.default')]
final class DefaultNormalizerConfigurator implements NormalizerBuilderConfigurator
{
public function configureNormalizerBuilder(NormalizerBuilder $builder): NormalizerBuilder
{
return $builder
->registerTransformer(
fn (DateTimeInterface $date) => $date->format('Y-m-d')
)
->registerTransformer(
fn (\App\Domain\Money $money) => [
'amount' => $money->amount,
'currency' => $money->currency->value,
]
);
}
}
#[\CuyZ\ValinorBundle\Cache\WarmupForMapper]
final readonly class ClassThatWillBeWarmedUp
{
public function __construct(
public string $foo,
public int $bar,
) {}
}
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.