php-soap / ext-soap-engine
ext-soap-engine 实现方案
Requires
- php: ~8.1.0 || ~8.2.0 || ~8.3.0
- ext-dom: *
- ext-soap: *
- azjezz/psl: ^2.1
- php-soap/engine: ^1.3|^2.0
- php-soap/wsdl: ^1.3
- symfony/options-resolver: ^5.4 || ^6.0 || ^7.0
Requires (Dev)
- php-soap/engine-integration-tests: ^1.4
- php-soap/xml: ^1.4
- phpunit/phpunit: ^10.0.19
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());