germania-kg / order-dispatcher
创建和处理订单
Requires
- php: ^7.1|^8.0
- germania-kg/responder: ^1.0
- nyholm/psr7: ^1.3
- psr/container: ^1.0|^2.0
- psr/http-message: ^1.0
- psr/log: ^1.1
- swiftmailer/swiftmailer: ^6.2
- twig/twig: ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.0
- laminas/laminas-log: ^2.12
- php-coveralls/php-coveralls: ^2.0
- phpspec/prophecy-phpunit: ^2.0
- phpunit/phpunit: ^9.0
- pimple/pimple: ^3.3
- spatie/phpunit-watcher: ^1.0
- swiftmailer/swiftmailer: ^6.2
- twig/twig: ^3.0
Suggests
- swiftmailer/swiftmailer: Sending emails
- twig/twig: Template engine
README
Germania KG · OrderDispatcher
寻找这些材料...
安装
$ composer require germania-kg/order-dispatcher
类和接口
处理订单
OrderInterface
public function getCustomerData() : array;
public function getItems() : iterable;
OrderFactoryInterface
public function createOrder( array $input) : OrderInterface; public function setItemFactory(ItemFactoryInterface $item_factory); public function getItemFactory() : ItemFactoryInterface;
OrderFactoryAbstract
这个抽象类实现了在 OrderFactoryInterface 中定义的 Item 工厂拦截器,并使用 ValidatorTrait。
public function setItemFactory(ItemFactoryInterface $item_factory); public function getItemFactory() : ItemFactoryInterface;
ArrayOrderFactory
从数组中创建一个 Order 实例,通常来自用户输入。
ArrayOrderFactory 扩展 OrderFactoryAbstract 并实现了 OrderFactoryInterface。
构造函数接受一个 ItemFactoryInterface、订单项目数组键和可选的 PSR-3 LoggerInterface。
<?php use Germania\OrderDispatcher\ArrayOrderFactory; use Germania\OrderDispatcher\FilterValidator; $item_factory = ... ; $logger = ...; $factory = new ArrayOrderFactory($item_factory, "items"); $factory = new ArrayOrderFactory($item_factory, "items", $logger); $customer_validation = new FilterValidator(array( "email" => FILTER_VALIDATE_EMAIL, "company" => FILTER_SANITIZE_FULL_SPECIAL_CHARS, "retailer_number" => [ "filter" => FILTER_VALIDATE_REGEXP, "options" => ['regexp'=>"/^[\d\-]+$/"] ], "privacyAck" => FILTER_VALIDATE_BOOLEAN )); // Set customer data validation $factory->setValidator( $customer_validation );
使用上述设置进行使用
$order = $factory->createOrder([ 'email' => "test@test.com", 'company' => "ACME Corp.", 'retailer_number' => "12345", 'privacyAck' => 1, 'items' => array( [ 'sku' => "foo" , "quantity" => 5 ] ) ]); $customer = $order->getCustomerData(); $items = $order->getItems();
OrderHandlerController
这个控制器类接受来自 ServerRequest 身体的用户输入,创建一个正在进行的订单对象并将其委托给给定的处理程序。
其构造函数接受一个 OrderFactoryInterface 实例、一个 OrderHandlerInterface 实例和可选的 PSR-3 LoggerInterface。
<?php use Germania\OrderDispatcher\OrderHandlerController; $factory = ... ; $handler = ... ; $logger = ... ; $controller = new OrderHandlerController($factory, $handler); $controller = new OrderHandlerController($factory, $handler, $logger);
给定一个 ServerRequest 和一个 Response 对象,像这样调用控制器
$request = $request->withParsedBody(array( 'email' => "test@test.com", 'company' => "ACME Corp.", 'retailer_number' => "12345", 'privacyAck' => 1, 'articles' => array( [ 'sku' => 'A1', 'quantity' => 100], [ 'sku' => 'B2', 'quantity' => 5] ) )); $response = $controller($request, $response); if ($reponse->getStatusCode != 200) { echo $resonse->getHeaderLine('X-Order-Dispatch-Message'); }
响应状态码
响应头
如果发生错误,响应对象将有一个包含抛出的异常类名的 X-Order-Dispatch-Message
头部
if (200 != $reponse->getStatusCode()) { echo $resonse->getHeaderLine('X-Order-Dispatch-Message'); // Germania\OrderDispatcher\Exceptions\OrderHandlerRuntimeException }
处理订单项
订单项是可以订购的东西。
Item 类和 ItemInterface
ItemInterface 扩展 \ArrayAccess
。
Item 类扩展 \ArrayObject
并实现 ItemInterface。
<?php use Germania\OrderDispatcher\ItemInterface; use Germania\OrderDispatcher\Item;
ItemFactoryInterface
public function createItem( array $order_item ) : ItemInterface;
SimpleItemFactory
根据任何数组数据创建一个“订单项”数组。扩展 ItemFactoryAbstract 并实现 ItemFactoryInterface。
<?php use Germania\OrderDispatcher\SimpleItemFactory; $item_factory = new SimpleItemFactory; $item = $item_factory->createItem([ 'sku' => 'foobar', 'quantity' => 100 ]);
ContainerItemFactory
使用此功能将订单项限制为仅从 PSR-11 Psr\Container\ContainerInterface
中的项目。需要指定用于检索项目的数组字段名称,构造函数可选地接受一个 PSR-3 Logger。
扩展 ItemFactoryAbstract 并实现 ItemFactoryInterface。
当项目不可用时,将抛出 ItemNotAvailableException
。
<?php use Germania\OrderDispatcher\ContainerItemFactory; use Germania\OrderDispatcher\Exceptions\ItemNotAvailableException; $available = new Psr11Container( ... ); $item_factory = new ContainerItemFactory($available, "sku"); $item_factory = new ContainerItemFactory($available, "sku", $logger); $sku = 'foobar'; try { $item = $item_factory->createItem([ 'sku' => $sku, 'quantity' => 100 ]); } catch (ItemNotAvailableException $e) { echo "$sku is not available"; }
ValidatorItemFactoryDecorator
此装饰器接受任何 ItemFactoryInterface 和一个 ValidatorInterface 来验证订单项数据。
<?php use Germania\OrderDispatcher\ValidatorItemFactoryDecorator; use Germania\OrderDispatcher\ContainerItemFactory; $inner = new ContainerItemFactory($available, "sku"); $validator = new SkuQtyItemValidator; $item_factory = ValidatorItemFactoryDecorator($inner, $validator);
渲染订单
渲染器用于从一个订单对象创建字符串表示,通常用于电子邮件。
RendererInterface
渲染器接受一个 template 字符串和一个上下文变量数组。如果出现错误,必须抛出 Germania\OrderDispatcher\Exceptions\RendererExceptionInterface
。
public function render( string $template, array $context = array()) : ?string;
TwigRenderer
TwigRenderer 实现了 RendererInterface。其构造函数接受一个 Twig 环境对象,并可选地接受一个包含默认上下文变量的数组。
<?php use Germania\OrderDispatcher\TwigRenderer; $twig = ... ; $renderer = new TwigRenderer($twig);
处理订单
OrderHandlerInterface
public function handle( OrderInterface $order, array $context = array()) : bool ;
SwiftMailerOrderHandler
SwiftMailerOrderHandler 实现了 OrderHandlerInterface。其构造函数接受一个 SwiftMailer 实例、一个邮件配置数组和一个 RendererInterface 实例。
通常,您将使用 TwigRenderer 作为 RendererInterface。
邮件配置数组必须包含 to
、from
、template
和 subject
元素。主题可以包含花括号中的字段变量,这些变量将从处理方法上下文中插入。
邮件配置数组中给出的 Subject 和 template 可以通过上下文数组中的 mailSubject
或 mailTemplate
条目来覆盖。
渲染器将传递包含额外 customer
、orderItems
和 datetimeNow
信息的处理程序上下文。
<?php use Germania\OrderDispatcher\SwiftMailerOrderHandler; $order = ...; $renderer = ... ; $swift_mailer = ...; $mail_config = array( 'to' => array("mail@test.com" => "John Doe"), 'from' => array("webshop@test.com" => "My Webshop"), 'template' => 'mail.tpl', 'subject' => "{foo} {bar}" ); $handler = new SwiftMailerOrderHandler($swift_mailer, $mail_config, $renderer); $handler->handle($order, [ 'foo' => "Order" 'bar' => "beverage" ]);
OrderHandlerChain
使用此处理程序通过多个处理程序对订单进行修改。
<?php use Germania\OrderDispatcher\OrderHandlerChain; $handlers = array(); $chain = new OrderHandlerChain($handlers); $handler2 = new ...; $chain->add( $handler2 );
验证器
ValidatorInterface
验证用户输入并返回清理后的数据。通常使用PHP的 filter_var_array
。
在编写自己的实现时,应添加缺失的字段并将其设置为 null
,任何额外的内容都应合并回去。
public function validate( array $input ): array;
ValidatorTrait
ValidatorInterface 的拦截器。
protected $validator; public function setValidator( ValidatorInterface $validator ); public function getValidator() : ValidatorInterface;
FilterValidator
此验证器使用PHP的 filter_var_array
检查用户输入。
- 将添加缺失的字段并将其设置为
null
。 - 将合并回额外的“未验证”内容,与原始的 filter_var_array 相反。
FilterValidator 实现 ValidatorInterface。
<?php use Germania\OrderDispatcher\FilterValidator; $fv = new FilterValidator([ "email" => FILTER_VALIDATE_EMAIL, "company" => FILTER_SANITIZE_FULL_SPECIAL_CHARS ]); $result = $fv->validate([ 'email' => 9999, 'company' => 'ACME Corp.', 'foo' => 'bar' ]); print_r($result); // Array // ( // [email] => false // [company] => ACME Corp. // [foo] => bar // )
SkuQtyItemValidator
这是一个预定义的验证器,用于检查用户输入的 sku
和 quantity
元素。它的工作方式与 FilterValidator:
- 将添加缺失的字段并将其设置为
null
。 - 将合并回额外的“未验证”内容,与原始的 filter_var_array 相反。
异常
- ItemInvalidUserDataException,当
sku
或quantity
缺失或为 false - ItemNotOrderedException,当
quantity
为 int 0 时。
SkuQtyItemValidator 实现 ValidatorInterface。
<?php use Germania\OrderDispatcher\SkuQtyItemValidator; use Germania\OrderDispatcher\Exceptions\ItemInvalidUserDataException; use Germania\OrderDispatcher\Exceptions\ItemNotOrderedException; $v = new SkuQtyItemValidator(); try { $v->validate([ 'sku' => 'foo', 'quantity' => 100 ]); } catch(ItemInvalidUserDataException $e) { } catch(ItemNotOrderedException $e) { // quantity was 0 (!== null) }