cuyz/valinor-bundle

`cuyz/valinor`的Symfony集成——一个帮助将任何输入映射到强类型值对象结构的库。

资助包维护!
romm

安装次数: 69,744

依赖者: 1

建议者: 0

安全性: 0

星标: 42

关注者: 3

分支: 4

公开问题: 0

类型:symfony-bundle

0.3.0 2024-05-27 09:26 UTC

This package is auto-updated.

Last update: 2024-08-27 10:00:33 UTC


README

Symfony logo Plus Valinor banner

Latest Stable Version PHP Version Require

Valinor库的Symfony集成。

Valinor负责将原始输入(JSON、普通数组等)构建和验证为对象,确保其处于完全有效状态。它允许在整个应用程序生命周期中使用这些对象,而不必担心其完整性。

验证系统将检测任何不正确的值,并通过提供精确且易于理解的错误消息来帮助开发者。

映射器可以处理原生PHP类型以及PHPStan和Psalm支持的其它高级类型,如形状数组、泛型、整数范围等。

安装

composer require cuyz/valinor-bundle
// config/bundles.php

return [
    // …
    CuyZ\ValinorBundle\ValinorBundle::class => ['all' => true],
];

映射器注入

可以将映射器实例注入任何带有类型TreeMapper的自定义服务。

use CuyZ\Valinor\Mapper\TreeMapper;

final class SomeAutowiredService
{
    public function __construct(
        private TreeMapper $mapper,
    ) {}
    
    public function someMethod(): void
    {
        $this->mapper->map(SomeDto::class, /* … */);
        
        // …
    }
}

它还可以手动注入到服务中...

...使用PHP文件
// 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),
        ]);
};
...使用YAML文件
services:
    Acme\SomeService:
        arguments:
            - '@CuyZ\Valinor\Mapper\TreeMapper'

为了更精细的控制,可以注入一个MapperBuilder实例。

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, /* … */);
        
        // …
    }
}

包配置

包的全球配置可以在配置文件中完成...

...使用PHP文件
// 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 a mapping error occurs during a console command, the output will
    // automatically be enhanced to show information about errors. The maximum
    // number of errors that will be displayed can be configured below, or set
    // to 0 to disable this feature entirely.
    $config->console()->mappingErrorsToOutput(15);

    // By default, mapper cache entries are stored in the filesystem. This can
    // be changed by setting the name of a PSR-16 cache service below.
    $config->cache()->service('app.custom_cache');

    // Cache entries representing class definitions won't be cleared when files
    // are modified during development of the application. This can be changed
    // by setting in which environments cache entries will be unvalidated.
    $config->cache()->envWhereFilesAreWatched(['dev', 'custom_env']);
};
...使用YAML文件
# config/packages/valinor.yaml

valinor:
    mapper:
        # Date formats that will be supported by the mapper by default.
        date_formats_supported:
            - '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.
        allowed_exceptions:
            - \Webmozart\Assert\InvalidArgumentException
            - \App\CustomException,

    console:
        # When a mapping error occurs during a console command, the output will
        # automatically be enhanced to show information about errors. The
        # maximum number of errors that will be displayed can be configured
        # below, or set to 0 to disable this feature entirely.
        mapping_errors_to_output: 15

    cache:
        # By default, mapper cache entries are stored in the filesystem. This
        # can be changed by setting the name of a PSR-16 cache service below.
        service: app.custom_cache

        # Cache entries representing class definitions won't be cleared when
        # files are modified during development of the application. This can be
        # changed by setting in which environments cache entries will be
        # unvalidated.
        env_where_files_are_watched: [ 'dev', 'custom_env' ]

其他功能

自定义映射器构建器

可以通过实现接口MapperBuilderConfigurator来自定义服务映射器构建器。

注意

如果此服务自动配置,它将自动使用,否则需要使用标签valinor.mapper_builder_configurator标记。

use CuyZ\Valinor\MapperBuilder;
use CuyZ\ValinorBundle\Configurator\MapperBuilderConfigurator

final class ConstructorRegistrationConfigurator implements MapperBuilderConfigurator
{
    public function configure(MapperBuilder $builder): MapperBuilder
    {
        return $builder
            ->registerConstructor(SomeDTO::create(...))
            ->registerConstructor(SomeOtherDTO::new(...));
    }
}

使用属性配置映射器行为

可以使用属性自动自定义映射器行为。

警告

此功能仅适用于自动注入的服务。

  • EnableFlexibleCasting —— 改变了映射器关于类型灵活性的几个行为。有关更多信息,请阅读文档

  • AllowSuperfluousKeys —— 允许在源数组中有冗余键,防止在值未绑定到任何对象属性/参数或形状数组元素时出错。有关更多信息,请阅读文档

  • AllowPermissiveTypes —— 允许在映射时使用宽泛的类型mixedobject

  • SupportDateFormats —— 配置映射器支持的日期格式。

use CuyZ\Valinor\Mapper\TreeMapper;
use CuyZ\ValinorBundle\Configurator\Attributes\AllowPermissiveTypes;
use CuyZ\ValinorBundle\Configurator\Attributes\AllowSuperfluousKeys;
use CuyZ\ValinorBundle\Configurator\Attributes\EnableFlexibleCasting;
use CuyZ\ValinorBundle\Configurator\Attributes\SupportDateFormats;

final class SomeService
{
    public function __construct(
        #[EnableFlexibleCasting]
        private TreeMapper $mapperWithFlexibleCasting,

        // or…
        #[AllowSuperfluousKeys]
        private TreeMapper $mapperWithSuperfluousKeys,

        // or…
        #[AllowPermissiveTypes]
        private TreeMapper $mapperWithPermissiveTypes,

        // or…
        #[SupportDateFormats('Y-m-d', 'Y/m/d')]
        private TreeMapper $mapperWithCustomDateFormat,
        
        // or a combination of the above…
        #[EnableFlexibleCasting, AllowSuperfluousKeys, …]
        private TreeMapper $mapperWithSeveralAttributes,
    ) {}
}

还可以通过使用接口MapperBuilderConfiguratorAttribute声明自定义配置器属性。

use Attribute;
use CuyZ\Valinor\MapperBuilder;
use CuyZ\ValinorBundle\Configurator\Attributes\MapperBuilderConfiguratorAttribute;
 
#[Attribute(Attribute::TARGET_PARAMETER)]
final class SomeCustomConfigurator implements MapperBuilderConfiguratorAttribute
{
    public function configure(MapperBuilder $builder): MapperBuilder
    {
        return $builder
            ->enableFlexibleCasting()
            ->allowSuperfluousKeys()
            ->supportDateFormats('Y/m/d');
    }
}

然后可以在服务中使用它

use CuyZ\Valinor\Mapper\TreeMapper;
use CuyZ\ValinorBundle\Configurator\Attributes\SomeCustomConfigurator;
 
final class SomeService
{
   public function __construct(
      #[SomeCustomConfigurator]
     private TreeMapper $mapperWithCustomConfig
  ) {}
}

控制台命令中的映射错误

当使用Symfony Console运行命令时,将捕获映射错误以增强输出,并提供更好的错误原因。

注意

可以配置将在包配置中显示的最大错误数在这里

输出示例

$ bin/console some:command

Mapping errors
--------------

A total of 3 errors were found while trying to map to `Acme\Customer`

 -------- ------------------------------------------------------------------------- 
  path     message                                                                  
 -------- ------------------------------------------------------------------------- 
  id       Value 'John' is not a valid integer.
  name     Value 42 is not a valid string.
  email    Cannot be empty and must be filled with a value matching type `string`.  
 -------- ------------------------------------------------------------------------- 
                                                                                                                        
 [INFO] The above message was generated by the Valinor Bundle, it can be disabled
        in the configuration of the bundle.

缓存预热

当使用Symfony的缓存预热功能——通常是bin/console cache:warmup——映射器缓存将自动为所有带有标签valinor.warmup的类进行预热。

此标签可以通过服务配置手动添加,或者使用WarmupForMapper属性自动为autoconfigured classes添加。

#[\CuyZ\ValinorBundle\Cache\WarmupForMapper]
final readonly class ClassThatWillBeWarmedUp
{
    public function __construct(
        public string $foo,
        public int $bar,
    ) {}
}

注意

WarmupForMapper属性会禁用分配给类的依赖注入自动绑定。尽管在大多数情况下,为将被映射器实例化的类进行自动绑定没有意义,但在某些情况下可能仍然需要,这时可以将属性的$autowire参数设置为true