crell/transformer

一个简单的对象转换库

2.0.0 2021-02-14 23:20 UTC

This package is auto-updated.

Last update: 2024-09-15 07:05:37 UTC


README

Build Status

这是一个简单的库,简化了基于类型PHP对象的转换管道的构建。

“这是什么意思?”

考虑以下场景:您有一些过程或一系列过程,最终应该得到某种类型的对象。然而,根据不同的用例,您的各种过程可能输出各种不同类型的对象。但是,您希望它们最终都成为那种最终类型。

这个库允许您创建“转换器”,这些转换器知道如何将一个对象转换为另一个。然后您可以轻松地将它们连接起来,并将任何已知如何处理的对象提供给主转换器。然后它将产生一个最终类型的对象。

作为一个具体的例子,假设您想要为您的工作框架(Symfony、Zend、无论什么)生成一个Response对象,但您的控制器可能返回多个特定于您的应用程序的领域对象。比如说,模型中的一个对象,或者该领域模型对象的HTML表示,或者包含该领域模型HTML表示的完整HTML页面。

  • 将领域模型对象渲染为HTML是您知道如何做的,但您并不总是想将其作为它自己的页面的主体显示。
  • 给定一个HTML片段,您知道如何将其渲染为HTML页面的主体。
  • 给定一个HTML页面,您知道如何将其包装为响应。

这些都是单独的任务,将数据从一个表示转换为另一个表示。

这些都是转换,由转换器执行。转换器只是一个PHP可调用,它接受一个类型的对象并返回另一个类型的对象。

用法

使用上面的例子,我们可以这样连接。

首先,我们有各种领域模型类

// A product from our domain.
class Product {}

// A Customer from our domain.
class Customer {}

// An HttpResponse object from our framework.
class Response {}

// Contains an HTML string and metadata.
class HtmlBody {} 

// Contains an HTML string and metadata.
class HtmlPage {} 

现在我们为它们设置转换器,并将它们连接到一个总线

// Create a new tranformer bus, which will process until it finds a Response.
$bus = new TransformerBus(Response::class);

// Register a transformer for Product objects.
$bus->setTransformer(Product::class, function(Product $p) {
  $fragment = new HtmlBody();
  // Do some business logic here.
  return $fragment;
});

// Register a transformer for Customer objects. Note that it's totally OK
// for multiple objects to get transformed to the same type.
$bus->setTransformer(Customer::class, function(Customer $p) {
  $fragment = new HtmlBody();
  // Do some business logic here.
  return $fragment;
});

// Register a transformer for HtmlBody objects, this one as a function.
function makePage(HtmlBody $p) {
  $page = new HtmlPage();
  // Do some business logic here.
  return $page;
}
$bus->setTransformer(HtmlBody::class, 'makePage');

// Register a transformer for HtmlPage objects. Any PHP callable works.
class PageTransformer {
  public function transform(HtmlPage $h) {
    $response = new Response();
    // Do some business logic here.
    return $response;
  }
}
$t = new PageTransformer();
$bus->setTransformer(HtmlBody::class, [$t, 'transform']);

现在我们可以这样使用这个总线

$p = getProductFromSomewhere();
$response = $bus->transform($p);

$c = getCustomerFromSomewhere();
$response = $bus->transform($c);

$h = getHtmlBodyFromSomewhere();
$response = $bus->transform($h);

$h = getHtmlPageFromSomewhere();
$response = $bus->transform($h);

// This is effectively a no-op.
$r = getResponseFromSomewhere();
$response = $bus->transform($r);

在这种情况下,只有合适的转换器才会执行,但我们最终都会得到一个可靠的 $response。这意味着,在一个Web框架中,我们的控制器可以返回 任何 一个 ProductCustomerHtmlBodyHtmlPageResponse,我们最终都会得到一个 Response

无疑还有许多其他用例,但这是我最初编写这个库时的想法。

反射总线

还有一个额外的实现,ReflectiveTransformerBus。它与TransformerBus的工作方式相同,但您可以这样注册转换器

$bus->setAutomaticTransformer(function(Product $p) {
  $fragment = new HtmlBody();
  // Do some business logic here.
  return $fragment.
});

它将使用反射来注册该可调用为Product类,而无需明确告知。这更方便,但反射过程会有一些开销。

安装

首选的安装方法是使用Composer,以下命令

composer require crell/transformer

有关更多详细信息,请参阅 [Composer 文档][2]。

另请参阅

对于使用Symfony框架的用户,还有一个变体可供使用,它将接受Symfony "扩展可调用",因此您可以注册服务作为转换器,并且它们将在使用之前/除非使用时才加载。请参阅 TransformerBundle

许可证

GNU Lesser General Public License,版本3或,根据您的选择,任何更新的版本。请参阅许可证文件获取更多信息。