一个提供处理请求和响应的简洁界面的SOAP客户端。
Requires
- php: ^8.1|^8.2|^8.3
- illuminate/support: ^10.0|^11.0
Requires (Dev)
- ext-soap: *
- laravel/pint: ^1.14
- mockery/mockery: ^1.4
- orchestra/testbench: ^8.0|^9.0
- pestphp/pest: ^2.0
- phpoption/phpoption: ^1.8.1
- spatie/ray: ^1.17
README
一个Laravel SOAP客户端,提供处理请求和响应的简洁界面。
文档
要求
- PHP 7.4 或更高版本
- Laravel 8.16 或更高版本
安装
您可以通过composer安装此包
composer require ricorocks-digital-agency/soap
注意:自v1.5.0版起,Soap需要PHP ^7.4
使用Soap
Soap可以通过提供的Facade进行访问
use RicorocksDigitalAgency\Soap\Facades\Soap Soap::to()
功能/API
头部
您可以使用withHeaders
方法设置每个SOAP请求的头部,这些头部将被传递给SOAP客户端。
Soap::to('...')->withHeaders(...$headers)->call('...');
每个头部都应该是一个Header
实例,它提供了一个流畅的界面来构建一个新的PHP Soap Header,可以按以下方式组合
$header = Soap::header() ->name('Authentication') ->namespace('test.com') ->data([ 'user' => '...', 'password' => '...' ]) ->mustUnderstand() ->actor('foo.co.uk')
这也可以表达为
$header = Soap::header('Authentication', 'test.com', [ 'user' => '...', 'password' => '...' ]) ->mustUnderstand() ->actor('foo.co.uk')
此外,可以使用soap_header
辅助方法
$header = soap_header('Authentication', 'test.com') ->data([ 'user' => '...', 'password' => '...' ])
头部数据可以是数组或
SoapVar
,根据SoapHeader
构造函数的要求
全局头部
Soap允许您设置应包含在每个请求中的头部
Soap::headers(...$headers)
同样,每个头部都应该是一个Header
的实例。
您可能还希望在每个请求上包含头部,但仅针对特定的端点或操作
// Only requests to this endpoint will include these headers Soap::headers(soap_header('Auth', 'test.com'))->for('https://api.example.com'); // Only requests to this endpoint and the method Customers will include these headers Soap::headers(soap_header('Brand', 'test.com'))->for('https://api.example.com', 'Customers');
这些调用通常放在您应用程序的一个服务提供者的boot
方法中。
到
要访问的端点
Soap::to('github.com/api')
函数
检索端点提供的函数
Soap::to('github.com/api')->functions()
这是PHP SoapClient _getFunctions()
方法的包装器。
调用
在端点上调用方法。
Soap::to('github.com/api')->call('merge')
该方法也可以作为魔术方法调用。
Soap::to('github.com/api')->merge()
参数
调用方法当然接受参数。传递的参数可以是数组
Soap::to('github.com/api')->call('merge', ['branch' => 'staging', 'credentials' => ['password' => '...'])
节点
为了简化您在请求中处理SOAP XML,Soap提供了一个方法来流畅地构建请求中的节点。
例如,假设以下节点是所需的内容。注意它没有主体。
<PullRequest branch="dev" target="main"> </PullRequest>
传递给底层php SoapClient
以构造此节点的数组如下
'PullRequest' => [ '_' => '', 'branch' => 'dev', 'target' => 'main' ]
_
是必需的,以便将信息设置为属性而不是主体。
但是,如果XML节点有主体,则不需要这样做。
<PullRequest branch="dev" target="main"> <Author>Ricorocks</Author> </PullRequest>
现在,数组如下
'PullRequest' => [ 'Author' => 'Ricorocks', 'branch' => 'dev', 'target' => 'main' ]
因此,为了防止混淆,Soap::node()
将允许智能构建传递给SoapClient
的php array
。
假设我们正在访问information
方法来查看拉取请求的详细信息
Soap::to('...') ->information('PullRequest' => soap_node(['branch' => 'dev', 'target' => 'main'])) 'PullRequest' => [ '_' => '', 'branch' => 'dev', 'target' => 'main' ] Soap::to('...') ->information('PullRequest' => soap_node(['branch' => 'dev', 'target' => 'main'])->body(['Author' => 'Ricorocks'])) 'PullRequest' => [ 'Author' => 'Ricorocks', 'branch' => 'dev', 'target' => 'main' ]
现在,只需通过添加或删除soap_node()
中的主体,输出的数组就会智能构建。
节点可以用Facade的Soap::node()
或辅助方法soap_node()
创建。
选项
您可以使用withOptions
方法为每个将要传递给SOAP客户端的SOAP请求设置自定义选项。
Soap::to('...')->withOptions(['soap_version' => SOAP_1_2])->call('...');
有关更多详细信息和支持选项,请参阅https://php.ac.cn/manual/en/soapclient.construct.php。
SOAP还提供了一些方法,这些方法为最常用的选项添加了语法糖,具体如下。
跟踪
SOAP允许您轻松跟踪与访问的SOAP端点的交互。
要跟踪所有请求,请在您的ServiceProvider
的注册方法中设置以下内容
Soap::trace()
现在,所有返回的Response
对象都将附加一个Trace
对象,通过$response->getTrace()
访问。它有四个属性,是SoapClient
上找到的相应方法的包装器
xmlRequest
(__getLastRequest
)xmlResponse
(__getLastResponse
)requestHeaders
(__getLastRequestHeaders
)responseHeaders
(__getLastResponseHeaders
)
跟踪也可以局部声明
Soap::to('...')->trace()->call('...')
现在,仅此Response
将具有有效的Trace
。
跟踪是null安全的。如果调用$response->getTrace()
而尚未设置Trace
,则返回一个新的Trace
。此Trace
的属性都将返回null
。
认证
您可以通过调用withBasicAuth
和withDigestAuth
分别使用基本或摘要进行身份验证。
Soap::to('...')->withBasicAuth('username', 'password')->call('...'); Soap::to('...')->withDigestAuth('username', 'password')->call('...');
全局选项
有时,您可能希望在每次SOAP请求中都包含同一组选项。您可以使用Soap
外观的options
方法来完成此操作
// Every request will include these options automatically Soap::options(['login' => 'foo', 'password' => 'bar']);
您还可能希望在每次请求中都包含选项,但仅限于特定的端点或操作
// Only requests to this endpoint will include these options Soap::options(['login' => 'foo', 'password' => 'bar'])->for('https://api.example.com'); // Only requests to this endpoint and the method Customers will include these options Soap::options(['login' => 'foo', 'password' => 'bar'])->for('https://api.example.com', 'Customers');
这些调用通常放在您应用程序的一个服务提供者的boot
方法中。
钩子
钩子允许您在SOAP发出请求之前和之后执行操作。这些钩子可以是局部的(按请求),也可以是全局的(应用于每个请求)。
如果您希望在beforeRequesting
钩子中更改Request
对象,可以这样做。这些更改将反映在实际请求中。实际上,这就是SOAP的include
功能工作的方式。
局部
要创建局部钩子,将beforeRequesting
或afterRequesting
链接到Request
对象
Soap::to('http://example.com') ->beforeRequesting(fn() => Log::info('Request going in!')) ->afterRequesting(fn() => Log::info('Request coming out!')) ->call('Action', []);
任何请求前的钩子将接收请求作为参数,而请求后的钩子将接收请求和响应作为参数。
全局
要创建全局钩子,请使用Soap::beforeRequesting
和Soap::afterRequesting
方法。
Soap::beforeRequesting(fn() => Log::info('Request going in!')); Soap::afterRequesting(fn() => Log::info('Request coming out!'));
任何请求前的钩子将接收请求作为参数,而请求后的钩子将接收请求和响应作为参数。
伪造
SOAP包括对伪造端点和操作以及检查请求和响应的完整支持。
要伪造所有SOAP请求,请调用Soap:fake()
。这将返回每个请求的空响应。您可能希望更具体一些,因此可以将端点数组作为键,响应对象作为值传递给fake
方法
Soap::fake(['http://endpoint.com' => Response::new(['foo' => 'bar'])]);
在上面的示例中,对http://endpoint.com
发出的任何SOAP请求都将被伪造,并返回包含正文['foo' => 'bar']
的Response
对象。
如果您还想指定SOAP操作,也很简单!只需在端点后添加:{ActionName}
即可,如下所示
Soap::fake(['http://endpoint.com:Details' => Response::new(['foo' => 'bar'])]);
现在,只有对Details
操作的SOAP请求将被模拟。
您还可以使用|
运算符指定多个操作
Soap::fake(['http://endpoint.com:Details|Information|Overview' => Response::new(['foo' => 'bar'])]);
现在,只有对Details
、Information
和Overview
操作的SOAP请求将被模拟。
检查请求
如果您已调用Soap::fake()
,SOAP将记录所有发出的请求。然后您可以按需检查这些请求。
Soap::assertSentCount($count)
Soap::assertSentCount($count)
如果您只想断言发送了n
个SOAP请求,则可以使用此方法,将所需的计数作为参数传入。
Soap::assertSent(callable $callback)
Soap::assertSent(callable $callback)
您可以进一步深入测试,确认特定的请求实际上已经发送,并且返回了预期的响应。您应该将一个闭包传递给此方法,它接收 $request
和 $response
作为参数,如果它们符合您的预期,则返回 true
。
Soap::assertNotSent(callable $callback)
这是 Soap::assertSent
的对立面。您可以确保没有发出特定的请求。同样,从闭包返回 true
将导致它通过。
Soap::assertNothingSent()
如果您只想确保绝对没有发送任何内容,可以调用此方法。它确实做了它所说的。
配置
Soap 的配置是通过您的服务提供者中的 boot()
方法中的 Soap
面板进行的。
包含
可以将参数设置为自动包含在所有请求中。这些可以是 数组
或 节点
Soap::include(['credentials' => soap_node(['user' => '...', 'password' => '...'])]);
您甚至可以使用点语法在数组键上,以便深入到请求体中。
Soap::include(['login.credentials' => soap_node(['user' => '...', 'password' => '...'])]);
通常,您会想要针对特定的端点或操作。您可以通过链式调用 for
方法来实现这一点。
// Only requests to https://api.example.com will include this data Soap::include(['credentials' => soap_node(['user' => '...', 'password' => '...'])])->for('https://api.example.com'); // Only requests to https://api.example.com calling the Customers method will include this data Soap::include(['credentials' => soap_node(['user' => '...', 'password' => '...'])])->for('https://api.example.com', 'Customers');
Ray 支持
本软件包为 Ray 提供了一方支持,Ray 是 Spatie 的一款出色的调试工具!我们提供了一些方法,您可以立即开始调试。
显然,您需要在本项目中安装 Ray 才能使此功能生效。
ray()->showSoapRequests()
这将在 SOAP 包中启用 Ray 支持。任何 SOAP 请求都将被记录在 Ray 应用程序中,以便您检查。
ray()->stopShowingSoapRequests()
这将在 SOAP 包中禁用 Ray 支持。如果之前启用,请求将停止记录。
如果您想在测试中使用 Ray 集成,请记住与您的其他提供者一起注册
RayServiceProvider
。
更新日志
有关最近更改的更多信息,请参阅 更新日志。
贡献
有关详细信息,请参阅 贡献。
安全性
如果您发现任何安全相关的问题,请通过电子邮件 hello@ricorocks.agency 联系我们,而不是使用问题跟踪器。
鸣谢
许可
MIT 许可证(MIT)。有关更多信息,请参阅 许可文件。