rezonant / mapper-bundle
一个为对象到对象映射(及其反向)提供灵活机制的 Symfony2 扩展包
Requires
- php: >=5.3.2
- doctrine/common: ~2.4
- symfony/framework-bundle: ~2.3 | ~3.0
- symfony/validator: ~2.3 | ~3.0
- symfony/yaml: ~2.3 | ~3.0
Suggests
- friendsofsymfony/rest-bundle: ~1.0
- jms/serializer-bundle: ~0.11|~1.0
This package is not auto-updated.
Last update: 2024-09-24 04:00:27 UTC
README
注意:此库尚未准备好供通用使用!这是一个如此之早期的预alpha版本!
此 Symfony2 扩展包提供了一种灵活的对象到对象映射(及其反向)机制。请注意,此扩展包不涵盖从请求数据构造模型对象,也不处理从模型创建响应文本,因为这两者都应该是您的[反]序列化器的责任,我们建议使用 JMS Serializer。
映射可以通过注解自动提供,也可以通过配置手动提供,或通过自定义映射提供者提供。调用者还可以明确指定要使用的映射对象。该扩展包具有内置的缓存机制,可以使用多种内置(或自定义)缓存策略之一。内置的缓存策略包括内存存储、基于 Doctrine-Commons Cache 对象的策略,以及一个在 Symfony 会话包中的几乎无用的实现。
此外,虽然我们没有明确测试此用例,但您可能可以使用此库在匿名(stdclass)对象之间进行自由声明性映射。当它们是对象到对象映射的一部分时,对此类关联数组的支持相当充分,因此映射到/从它们应该可以工作,但如果我们的测试没有覆盖您的使用,那么效果可能会有所不同。
简介:在 RESTful 服务中使用
虽然实现相当通用,但此扩展包主要设计用于在 Symfony2 编写的 RESTful 服务中使用。标准的 Symfony2+FOSRest+JMS 项目通常通过 FOSRest body 监听器和 JMS 序列化器自动从请求数据获取模型对象。然后,可以使用 Symfony 验证器在继续之前断言用户数据的有效性。
另一方面,使用响应监听器功能的 FOSRestControllers 通常返回模型对象(而不是 Symfony HTTP Kernel 响应对象),这些对象将自动使用 JMS 序列化。然后,可以使用 FOSRest 内置的 "Accepts" 或基于扩展的格式化提示来选择基于 API 消费者想要的内容的输出格式。
您要(反)序列化到的模型对象应该是与您的 RESTful API 相关联的类,而不是您的实体层。这样做的一个原因可能是您可能需要支持 API 的多个版本。那么,您应该如何处理将 RESTful 模型转换为底层持久化对象呢?
RezonantMapperBundle 提供了一种简单但强大的对象到对象映射方法。内置的基于注解的映射器允许您声明性地指定源对象字段的目的地。请注意,尚不可用目的地驱动注解,但可以通过编写新的 AnnotationMapProvider 变体轻松添加。
专注于源驱动注解的决定受到此库主要用例的影响:将模型(服务层)数据映射到实体(持久层)数据及其反向。由于在 API 的单个版本中可能有多个模型类映射到相同的实体,并且可能有多个 API 版本,因此坚持使用源驱动注解是有意义的,因为它强制执行与您的服务相同的依赖关系图:您的 API 层依赖于您的持久层,但您的持久层不依赖于您的 API 层。话虽如此,如果您需要,您可以在库上添加支持。
安装
注意:这仍然是一个预alpha版本。由于没有发布版本,您必须依赖dev-master(前沿)。我们对API的稳定性不做任何保证,但希望这很快会改变。一旦版本被标记,将遵循严格的语义版本。
$ composer require rezonant/mapper-bundle=dev-master
您还必须在app/AppKernel.php中依赖此包。
$bundles = array(
...,
new Rezonant\MapperBundle\RezonantMapperBundle()
)
如果您不这样做,您将能够使用包的类,但没有任何Symfony DI服务可用,并且您的配置将被忽略。
使用Mapper服务
调用Mapper最简单的方法是允许映射提供者完成繁重的工作。
$dest = $mapper->map($sourceInstance, "ABC\MyDestinationClass");
上面,通过咨询所有注册的映射提供者以找到源和目标类之间的有效映射来查找映射。如果找到,则使用它。如果没有找到,则抛出异常(Rezonant\MapperBundle\Exceptions\UnableToMapException)。
您还可以通过map()的第三个参数显式提供映射。您可以使用MapBuilder API与此结合,以生成任意映射。
$map = new MapBuilder()
->field(new Reference("fromField"), new Reference("toField"))
->build();
$dest = $mapper->map($sourceInstance, "ABC\MyDestinationClass", $map);
基于注解的映射
该包支持指定字段到字段映射的源驱动注解。
use Rezonant\MapperBundle\Annotations as Mapper;
class MyModel {
/**
* @Mapper\MapTo("toField")
*/
public $fromField;
}
对于深层模型结构,您必须确保使用@Mapper\Type()注解指定类型。如果您还使用JMS serializer,您可以使用@JMS\Type()注解代替,并且MapperBundle将尊重它。两个类之间的映射将自动处理所有子类。
在上面的示例中,$fromField字段将映射到目标$toField。
基于配置的映射
在您的config.yml(或使用Symfony配置资源的地方)中
rezonant_mapper:
maps:
- source: ABC\MySourceClass
destination: ABC\MyDestinationClass
fields:
- from: fromField
to: toField
您还可以在每个字段下指定子映射,当源值是对象,而目标值是不同类型的对象时使用。
rezonant_mapper:
maps:
- source: ABC\MySourceClass
destination: ABC\MyDestinationClass
fields:
- from: fromField
to: toField
map:
fields:
- from: deeperFromField
to: deeperToField
您还可以使用深层引用。
rezonant_mapper:
maps:
- source: ABC\MySourceClass
destination: ABC\MyDestinationClass
fields:
- from: fromField
to: someField.someOtherField.toField
map:
fields:
- from: anotherField.deeperFromField
to: deeperToField
请注意,如果可能,每个字段引用涉及的类型将使用PHP反射自动检测。您也可以显式指定这些。
rezonant_mapper:
maps:
- source: ABC\MySourceClass
destination: ABC\MyDestinationClass
fields:
- from:
name: fromField
type: \TypeOfThisField
to:
name: someField.someOtherField.toField
types: [\TypeOfSomeField, \TypeOfSomeOtherField, \TypeOfToField]
这可能是在无法从反射和/或注解中检测到此类信息,或者当在映射第一次构建时不希望承担这种开销时所需的(但不要忘记缓存系统)。
Symfony2中的使用
安装后,您可以依赖@rezonant.mapper服务来获取配置好的Mapper服务实例。
配置
rezonant_mapper配置部分可以用于很多不仅仅是声明映射的事情。
启用/禁用映射提供者
您可以控制使用哪些映射提供者。以下示例显示了默认值
rezonant_mapper:
providers:
annotations:
enabled: true
config:
enabled: true
custom: []
"custom"字段是一个实现MapProviderInterface的类的数组,这些类应用作映射提供者。
缓存
可以通过操作配置中的"缓存"部分来控制包含的缓存层。以下显示了默认值
rezonant_mapper:
caching:
enabled: false
strategy: 'Rezonant\MapperBundle\Cache\Strategies\MemoryCacheStrategy'
"enabled"标志将启用/禁用缓存引擎。"strategy"字段允许您指定要使用的策略类。您可以实施自己的策略,通过实现Rezonant\MapperBundle\Cache\CacheStrategyInterface或使用Rezonant\MapperBundle\Cache\Strategies命名空间中找到的内置之一。值得注意的是DoctrineCacheStrategy,它允许您包装任何Doctrine-Commons Cache对象。Doctrine-Commons附带了许多缓存提供程序,包括APC和Memcache。
Symfony2之外的使用
即将推出!此软件包是针对 Symfony2 应用程序内核的 Symfony2 依赖注入包,因此它旨在与 Symfony 的依赖注入器一起使用。其功能目前无法以非 Symfony 的方式使用,但未来可能会改变。在此期间,即使您不使用 Symfony DI,也可以使用 Composer 拉取此项目,并使用 Rezonant\MapperBundle\Mapper 类手动构建 Mapper 服务。如果您要构建自己的实例,您应提供 MapProvider 实例(我们建议使用 AnnotationMapper,您需要依赖 Doctrine Commons 并提供 AnnotationReader)。如果您打算始终传递显式的映射,可以传递 NULL 作为映射提供者。
use Rezonant\MapperBundle\Mapper;
use Rezonant\MapperBundle\Providers\AnnotationMapProvider;
use Doctrine\Common\Annotations\AnnotationReader;
$mapper = new Mapper(new AnnotationMapProvider(new AnnotationReader()));
您还可以使用 Rezonant\MapperBundle\Providers\ConfigMapProvider 向 Mapper 服务注入多个预制的映射。只需手动或使用 Rezonant\MapperBundle\MapBuilder 构建映射,然后将它们作为数组传递给新的 ConfigMapProvider,然后使用该提供者作为您的 Mapper 实例。
缓存
可以通过构建 CacheProvider 并将您选择的 CacheStrategy 实现及其 MapProvider 传递给它,在不使用 Symfony 配置层的情况下使用缓存。您可以通过使用 Rezonant\MapperBundle\Providers\MapProviderModerator 类在几个 MapProvider 之间进行调节。这是 Symfony 包内部根据 rezonant_mapper 配置部分构建 Mapper 服务的 MapProvider 的方式。
测试
要运行测试,您(目前)必须构建一个 Symfony 项目并将源代码符号链接到其中。
$ cd mapper-bundle
$ symfony new symfony2
$ ln -s ../../src/Rezonant symfony2/src/Rezonant
$ phpunit