これで SOAP の学習は終了です。これは、学習プロセス中のいくつかのメモと経験を記録する最後の記事です。
最初の 3 つの記事は次のとおりです:
「SOAP の概要」
「SOAP Web サービスの概要」
「PHP SOAP 拡張機能の使用法」
以下はリクエスト インターフェースによって送信されるコンテンツです:
POST /webservices/qqOnlineWebService.asmx HTTP/1.1Host: www.webxml.com.cnConnection: Keep-AliveUser-Agent: PHP-SOAP/5.4.29Content-Type: application/soap+xml; charset=utf-8; action="http://WebXml.com.cn/qqCheckOnline"Content-Length: 247<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://WebXml.com.cn/"> <env:Body> <ns1:qqCheckOnline> <ns1:qqCode>8698053</ns1:qqCode> </ns1:qqCheckOnline> </env:Body></env:Envelope>
SOAP リクエストが実際にはサーバーに送信される POST リクエストであることがわかります。送信内容はSOAPメッセージ(今回呼び出したインターフェースのメソッドやパラメータなどを示す)です。
この POST リクエストには、送信するコンテンツ タイプが application/soap+xml であり、ユーザー エージェントが PHP-SOAP/5.4.29 であるなど、いくつかの特徴があります。その他の特徴については、あまり説明する必要はありません。 。
SOAP 拡張機能の役割
それでは、なぜ SOAP 拡張機能を使用するのでしょうか? 公式サイトにあるし、C言語で書かれているのでとても速いし、パッケージもしっかりしていて、面倒なXMLコードを自分で書く必要がないので、私はこれを使っています。
言い換えれば、SOAP 拡張機能は、実際には、SOAP サービスを処理するために特別に設計された、より使いやすく高速な HTTP パッケージ化ライブラリです。これについては、それほど深い意味はありません。
使用方法
PHP のヘルプ マニュアルには、SOAP 拡張機能に関する詳細なドキュメントがあり、特に、マニュアルの最後にいくつかのユーザー コメントとコード スニペットが記載されています。基本的に、問題の最も一般的な部分を解決します。以下に、開発プロセス中に遭遇したいくつかの問題と、解決策、注意が必要な点を記録します。現在、基本的にすべての SOAP Web サービスは WSDL インターフェース記述ファイルを提供するため、基本的に非 WSDL モードを考慮する必要はありません。
PHP SOAP 拡張機能は、SOAP 1.1 と SOAP 1.2 の両方のバージョンをサポートしています。一般的に、現在のインターフェイスは基本的にこれら 2 つの SOAP プロトコル バージョンとの通信を同時にサポートしています。この場合、当然、SOAP 1.2 の上位バージョンが使用されます。実際、どのバージョンを使用していても、SOAP 拡張機能を使用してサービスを呼び出している場合、拡張機能を使用するプロセスに違いはなく、同じです。次のように、SoapCient の初期化時にsoap_version を SOAP_1_1 または SOAP_1_2 に設定する必要があるだけです:
// SOAP 1.1 $client = new SoapClient($wsdl, [ 'soap_version' => SOAP_1_1]);// SOAP 1.2$client = new SoapClient($wsdl, [ 'soap_version' => SOAP_1_2]);
上で述べたように、今日のサービスは基本的に WSDL 記述ファイルを提供します。この場合、次のようにすることができます。これら 2 つのクラス、SoapParam と SoapVar は基本的に無視します。SOAP がこれら 2 つのクラスを提供するのは、主に PHP SOAP 拡張機能が WSDL 記述ファイルを持たない一部のサービスを使用できるようにするためです。もちろん、このような状況は基本的には存在しません。
このメソッドも同様です。WSDL モードでは、呼び出す必要があるメソッドは SoapClient オブジェクトのメソッドとして呼び出すことができるため、通常、このメソッドは非 WSDL モードでのみ使用されます。ただし、呼び出しメソッドの URI がデフォルト URI と異なる場合、またはメソッド呼び出し時に SOAP ヘッダーをメソッドに持ち込む必要がある場合は、__soapCall メソッドを使用する必要があります。以下は公式マニュアルからの抜粋です:
これは、SOAP 呼び出しを行うために使用される低レベルの API 関数です。通常、WSDL モードでは、SOAP 関数は SoapClient オブジェクトのメソッドとして呼び出すことができます。非 WSDL モードで、soapaction が不明な場合、uri がデフォルトと異なる場合、または SOAP ヘッダーを送信および/または受信する場合に便利です。以下にいくつかの例を見てみましょう。同様に、インターネット上で無料で使用できる SOAP サービスを引き続き使用して協力しています。このサービスの主な機能は、QQ 番号を通じてユーザーのオンライン ステータスを照会することです。サービス アドレス
サービスを要求するときに送信する必要がある SOAP メッセージは次のとおりです:
メソッド名を使用してインターフェイスを呼び出します:<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"> <soap12:Body> <qqCheckOnline xmlns="http://WebXml.com.cn/"> <qqCode>string</qqCode> </qqCheckOnline> </soap12:Body></soap12:Envelope>ログイン後にコピー
<?php$wsdl = 'http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl';$client = new SoapClient($wsdl, [ 'soap_version' => SOAP_1_2]);$client->qqCheckOnline([ 'qqCode' => 8698053]));
__soapCall メソッドを使用してインターフェイスを呼び出します:
<?php$wsdl = 'http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl';$client = new SoapClient($wsdl, [ 'soap_version' => SOAP_1_2]);$client->__soapCall('qqCheckOnline', [ ['qqCode' => 8698053]]);
パラメータに注目してください: 2 つの呼び出し方法は異なります。メソッド名を介して直接呼び出す場合、パラメーターは 1 次元配列ですが、__soapCall メソッドを介して呼び出す場合、パラメーターは 2 次元配列になります。これが両者の違いの 1 つです。
还有第二个区别,就是 __soapCall 方法可以在调用接口时,添加额外的 SOAP Header,比如这样:
$wsdl = 'http://www.example.com/service.asmx?wsdl';$client = new SoapClient($wsdl, [ 'soap_version' => SOAP_1_2]);$auth = ['sAuthenticate' => 'ab3cde34f5r4545g'];$namespace = 'http://www.example.com';$header = new SoapHeader($namespace, 'AuthenHeader', $auth, false);$client->__soapCall("SomeFunction", $parameters, null, $header);
虽然 SoapClient 也有 __setSoapHeaders 方法,但是它会给该实例的所有方法都添加上 SOAP Header,如果存在有些方法需要 SOAP Header 而有些又不需要的话,那么就必须使用 __soapCall 方法,针对某个方法来添加 SOAP Header 了。
实际上,在 WSDL 模式下,如果不需要发送 SOAP Header 的话,那么 namespace 是用不上的,因为 namespace 实际上已经在 WSDL 文件中有所描述了,PHP 的 SOAP 扩展会自动把它从 WSDL 文件中解析出来,用于构造 SOAP 请求。如果 SOAP 消息中,需要添加 SOAP Header 的话,那么必须提供 namespace。举个例子:
比如说,有一个服务它需要你发送的 SOAP 消息中必须有 SOAP Header,像下面一样:
<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:soap12="http://www.w3.org/2003/05/soap-envelope"> <soap12:Header> <AuthenHeader xmlns="http://www.example.cn"> <sAuthenticate>string</sAuthenticate> </AuthenHeader> </soap12:Header> <soap12:Body> <GetUserInfoById xmlns="http://www.example.cn"> <UserID>int</UserID> </GetUserInfoById> </soap12:Body></soap12:Envelope>
下面是构造该 SOAP 请求的代码:
<?php$wsdl = 'http://www.example.com/service.asmx?wsdl';$client = new SoapClient($wsdl, [ 'soap_version' => SOAP_1_2]);$auth = ['sAuthenticate' => 'ab3cde34f5r4545g'];$namespace = 'http://www.example.com';$header = new SoapHeader($namespace, 'AuthenHeader', $auth, false);$client->__setSoapHeaders($header); $response = $client->GetUserInfoById([ 'UserID' => 100]);
可以看到,使用 SoapHeader 来构建一个 SOAP Header 时,必须提供 namespace,而且是正确的命名空间。
其实,构造一个 SOAP Header 的方法不止这一种写法,还有其他写法,比如你还可以这样构造与上面一样的 SOAP 消息:
<?phpclass AuthenHeader{ private $sAuthenticate; public function __construct($auth) { $this->sAuthenticate = $auth; }}$wsdl = 'http://www.example.com/service.asmx?wsdl';$client = new SoapClient($wsdl, [ 'soap_version' => SOAP_1_2 ]);$auth = 'ab3cde34f5r4545g';$namespace = 'http://www.example.com';$authenHeader = new AuthenHeader($auth);$header = new SoapHeader($namespace, 'AuthenHeader', $authenHeader, false);$client->__setSoapHeaders($header);$response = $client->GetUserInfoById([ 'UserID' => 100 ]);
关于 SoapHeader 其他更多的用法,推荐翻阅 PHP 手册中的 SOAP 章节。
服务端在处理客户端请求发生错误时,将会抛出 SoapFault 异常。对于 SOAP 扩展中,哪些方法可能会抛出异常可以查看手册。一旦发生了异常,我们都应该捕捉它们,并妥善处理。像下面这样:
try { $client = new SoapClient($wsdl, [ 'trace' => true, 'soap_version' => SOAP_1_2 ]); .....} catch(SoapFault $e) { //在这里处理异常}
这两个方法可以查看最近一次请求和响应的内容,这两个方法对于调试很有帮助。当然,这两个方法只有在 SoapClient 实例化时,trace 参数设置为 true 才会生效。比如像这样:
<?php$wsdl = 'http://www.webxml.com.cn/webservices/qqOnlineWebService.asmx?wsdl';$client = new SoapClient($wsdl, [ 'trace' => true, 'soap_version' => SOAP_1_2]);$client->qqCheckOnline([ 'qqCode' => 8698053]));echo $client->__getLastRequest();echo $client->__getLastResponse();
getLastRequest() 输出的内容:
<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://WebXml.com.cn/"> <env:Body> <ns1:qqCheckOnline> <ns1:qqCode>8698053</ns1:qqCode> </ns1:qqCheckOnline> </env:Body></env:Envelope>
getLastResponse() 输出的内容:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <qqCheckOnlineResponse xmlns="http://WebXml.com.cn/"> <qqCheckOnlineResult>Y</qqCheckOnlineResult> </qqCheckOnlineResponse> </soap:Body></soap:Envelope>
在调试 SOAP 服务接口时,我们可以使用功能强大的 SoapUI 工具,可以很方便地调试接口。
上面都是自己在学习 PHP SOAP 扩展时的一些零散的笔记,如果有不对的地方,希望大家指出,谢谢。(本文已存档 GitHub)