crell / transformer
一个简单的对象转换库
Requires
- php: >=7.4.0
Requires (Dev)
- phpunit/phpunit: ^7.0 || ^8.0 || ^9.0
This package is auto-updated.
Last update: 2024-09-15 07:05:37 UTC
README
这是一个简单的库,简化了基于类型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框架中,我们的控制器可以返回 任何 一个 Product
、Customer
、HtmlBody
、HtmlPage
或 Response
,我们最终都会得到一个 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或,根据您的选择,任何更新的版本。请参阅许可证文件获取更多信息。