php-soap/ext-soap-engine

ext-soap-engine 实现方案

1.6.0 2024-01-26 09:44 UTC

This package is auto-updated.

Last update: 2024-08-26 10:58:17 UTC


README

此包是一个 SOAP 引擎,利用 PHP 的 ext-soap 扩展的内置函数。

它基本上是将 SoapClient 内部翻转:所有内置的编码、解码和 HTTP 传输功能都可以独立使用。

如果你的包中包含 SoapClient,你可能考虑使用这个包作为替代方案

  • 它让你完全控制 HTTP 层。
  • 它验证你传递给 SoapClient$options,并给出有意义的错误。
  • 它将类型和方法转换为真实对象,以便你可以实际使用这些信息。
  • 它使得在不对服务器进行任何 SOAP 调用的同时使用编码/解码逻辑成为可能。
  • ...

想要帮忙?💚

想了解更多关于本项目未来的信息?查看我们将要工作的 下一个大项目 列表。

安装

composer require php-soap/ext-soap-engine

示例用法

此示例包含了一个高级的设置,用于创建一个灵活的基于 ext-soap 的引擎。它展示了你可以用于配置 PHP 的 SoapClient 并将其转换为 SOAP 引擎的主要组件。

use Soap\Engine\SimpleEngine;
use Soap\ExtSoapEngine\AbusedClient;
use Soap\ExtSoapEngine\Configuration\ClassMap\ClassMapCollection;
use Soap\ExtSoapEngine\Configuration\TypeConverter\TypeConverterCollection;
use Soap\ExtSoapEngine\ExtSoapDriver;
use Soap\ExtSoapEngine\ExtSoapOptions;
use Soap\ExtSoapEngine\Transport\ExtSoapClientTransport;
use Soap\ExtSoapEngine\Transport\TraceableTransport;

$engine = new SimpleEngine(
    ExtSoapDriver::createFromClient(
        $client = AbusedClient::createFromOptions(
            ExtSoapOptions::defaults($wsdl, [
                'soap_version' => SOAP_1_2,
            ])
                ->disableWsdlCache()
                ->withClassMap(new ClassMapCollection())
                ->withTypeMap(new TypeConverterCollection())
        )
    ),
    $transport = new TraceableTransport(
        $client,
        new ExtSoapClientTransport($client)
    )
);

获取 SOAP 资源

$result = $engine->request('SomeMethod', [(object)['param1' => true]]);

// Collecting last soap call:
var_dump($transport->collectLastRequestInfo());

你仍然可以在实际的 SOAP 客户端上设置高级配置

$client->__setLocation(...);
$client->__setSoapHeaders(...);
$client->__setCookie(...);

读取/解析元数据

var_dump(
    $engine->getMetadata()->getMethods(),
    $engine->getMetadata()->getTypes()
);

$methodInfo = $engine->getMetadata()->getMethods()->fetchByName('SomeMethod');

引擎

此包提供以下引擎组件

  • ExtSoapEncoder: 使用 PHP 的 SoapClient 将混合请求体编码为 SOAP 请求。
  • ExtSoapDecoder: 使用 PHP 的 SoapClient 将 SOAP 响应解码为混合数据。
  • ExtSoapMetadata: 将 PHP 的 SoapClient 中的方法和类型解析为更易用的形式。
  • ExtSoapDriver: 将 ext-soap 编码器、解码器和元数据工具组合成一个可用的 ext-soap 预设。

传输

  • ExtSoapClientTransport: 使用 PHP 的 SoapClient 处理 SOAP 请求。
  • ExtSoapServerTransport: 使用 PHP 的 SoapServer 处理 SOAP 请求。它可以在单元测试期间使用。
  • TraceableTransport: 可以用于装饰另一个传输并跟踪最后请求和响应。它应该作为在 SoapClient 上获取它的替代方案。

在 ext-soap 中,有关 HTTP 层有一些已知问题。因此,我们建议使用基于 PSR-18 的传输 而不是上面的传输。除了处理一些问题外,它还提供了一套中间件来处理一些你可能无法用常规 SoapClient 解决的常见问题。

配置选项

ExtSoapOptions

本软件包为所有可用的 \SoapClient 选项提供了一个小封装。它提供了合理的默认选项。如果您想设置特定的选项,可以以合理的方式完成:在将选项传递给 \SoapClient 之前,将验证这些选项。这样,您将花费更少的时间浏览官方的PHP文档。

<?php

use Soap\ExtSoapEngine\ExtSoapOptions;
use Soap\ExtSoapEngine\Wsdl\Naming\Md5Strategy;use Soap\ExtSoapEngine\Wsdl\TemporaryWsdlLoaderProvider;
use Soap\Psr18Transport\Wsdl\Psr18Loader;
use Soap\Wsdl\Loader\FlatteningLoader;

$options = ExtSoapOptions::defaults($wsdl, ['location' => 'http://somedifferentserver.com'])
    ->disableWsdlCache()
    ->withClassMap(\MyClassMap::getCollection())
    ->withWsdlProvider(new TemporaryWsdlLoaderProvider(
        new FlatteningLoader(new Psr18Loader($httpClient)),
        new Md5Strategy(),
        'some/dir'
    ));

$typemap = $options->getTypeMap();
$typemap->add(new \MyTypeConverter());

WsdlProvider

WsdlProvider 可以用来加载 WSDL。由于 ext-soap 需要可加载的 URL,它的工作方式与 php-soap/wsdl 内部的 wsdl loaders 略有不同。

use Soap\ExtSoapEngine\ExtSoapOptions;

$options = ExtSoapOptions::defaults($wsdl)
    ->withWsdlProvider($yourProvider);

本软件包包含一些内置提供者

InMemoryWsdlProvider

通过使用内存中的 WSDL 提供者,您可以使用完整的 XML 版本的 WSDL 作为源。这可能在测试期间很有用,但可能不应用于生产。

<?php
use Soap\ExtSoapEngine\Wsdl\InMemoryWsdlProvider;

$provider = new InMemoryWsdlProvider();
$wsdl = ($provider)('<definitions ..... />');

PassThroughWsdlProvider

默认情况下使用透传 WSDL 提供者。您可以传递任何通常传递给内置 SOAP 客户端 wsdl 选项的字符串。不会执行额外的检查,文件的加载将由内部 SoapClient 类处理。

<?php
use Soap\ExtSoapEngine\Wsdl\PassThroughWsdlProvider;

$provider = new PassThroughWsdlProvider();
$wsdl = ($provider)('some.wsdl');

PermanentWsdlLoaderProvider

此提供者可以永久缓存一个(远程)WSDL。这在 WSDL 不太可能更改的生产环境中非常有用。您可以通过 cronjob 等方式强制将其加载到永久位置。这将提高性能,因为 soap-client 不必远程获取 WSDL。您可以使用任何 WSDL loader

<?php
use Soap\ExtSoapEngine\Wsdl\Naming\Md5Strategy;
use Soap\ExtSoapEngine\Wsdl\PermanentWsdlLoaderProvider;
use Soap\Wsdl\Loader\FlatteningLoader;
use Soap\Wsdl\Loader\StreamWrapperLoader;

$provider = new PermanentWsdlLoaderProvider(
    new FlatteningLoader(new StreamWrapperLoader()),
    new Md5Strategy(),
    'target/location'
);

// Force downloads:
$provider = $provider->forceDownload();

$wsdl = ($provider)('some.wsdl');

TemporaryWsdlLoaderProvider

此提供者可以通过 WSDL loader 临时获取一个(远程)WSDL。这可以在 WSDL 文件可能频繁更改的开发中使用。您可以使用任何 WSDL loader

<?php
use Soap\ExtSoapEngine\Wsdl\Naming\Md5Strategy;
use Soap\ExtSoapEngine\Wsdl\TemporaryWsdlLoaderProvider;
use Soap\Wsdl\Loader\FlatteningLoader;
use Soap\Wsdl\Loader\StreamWrapperLoader;

$provider = new TemporaryWsdlLoaderProvider(
    new FlatteningLoader(new StreamWrapperLoader()),
    new Md5Strategy(),
    'target/location'
);

$wsdl = ($provider)('some.wsdl');

编写自己的 WSDL 提供者

没有找到您需要的 WSDL 提供者?不用担心!创建自己的 WSDL 提供者非常简单。您唯一需要做的是实现 WsdlProvider 接口。

namespace Soap\ExtSoapEngine\Wsdl;

interface WsdlProvider
{
    /**
     * This method can be used to transform a location into another location.
     * The output needs to be processable by the SoapClient $wsdl option.
     */
    public function __invoke(string $location): string;
}

ClassMap

通过提供类映射,您让 ext-soap 了解如何将特定 SOAP 类型的数据转换为实际的类。

用法

use Soap\ExtSoapEngine\Configuration\ClassMap\ClassMap;
use Soap\ExtSoapEngine\ExtSoapOptions;

$options = ExtSoapOptions::defaults($wsdl);
$classmap = $options->getClassMap();
$classmap->set(new ClassMap('WsdlType', 'PhpClassName'));

TypeConverter

某些异类 XSD 类型很难转换为 PHP 对象。一个典型的例子是日期:有些人喜欢将其作为时间戳,有些人想将其作为 DateTime,... 通过添加自定义 TypeConverters,可以将 WSDL 类型转换为 / 从 PHP 类型。

这些 TypeConverters 默认添加

  • DateTimeTypeConverter
  • DateTypeConverter
  • DoubleTypeConverter
  • DecimalTypeConverter

您也可以通过实现 TypeConverterInterface 来创建自己的转换器。

用法

use Soap\ExtSoapEngine\Configuration\TypeConverter;
use Soap\ExtSoapEngine\ExtSoapOptions;

$options = ExtSoapOptions::defaults($wsdl);
$typemap = $options->getTypeMap();
$typemap->add(new TypeCOnverter\DateTimeTypeConverter());
$typemap->add(new TypeConverter\DecimalTypeConverter());
$typemap->add(new TypeConverter\DoubleTypeConverter());