SOAP extensionでSOAP Server
サンプルは、EXPERIENCEで実際に確認できるようにしてますので、気になる方は見てみてください。
以前にPHP4+PEAR SOAP+Google Web APIsでGoogle検索とかPHP5のSOAP extension+Google Web APIsでGoogle検索といったSOAP Clientとしての使い方を確認してきましたが、「Clientと来ればServer」ということ(?)で今度はSOAP Serverを試してみます。PHP5.0.0で導入されてまだ枯れていない(と思われる)extensionですが、2005/06/10にリリースされたPHP5.1.0β1でもかなりの修正がされているようですので今後が楽しみです。
SOAPServerに関してのドキュメントは、やはりPHP日本語マニュアルを参照してください。
今回のサンプルですが、次の4つのサービスを提供するSOAP Serverを作ってみました。
-
add:数値を2つ受け取り、加算した結果を返す
-
addByArray:数値を格納した配列を受け取り、合算した結果を返す
-
hello:文字列を1つ受け取り、メッセージを返す
-
helloByObj:オブジェクトを受け取り、メッセージを返す
どれもありがちな(?)サービスですが、数値・文字列(日本語も含む)などの基本型、配列、オブジェクトを引数とする場合での動作を確認したかったのでサービス内容はかなり単純にしてあります。
さて、このSOAP ServerのPHPコードは以下のようになります。
●SoapServer_test.php
<?php
mb_internal_encoding('utf-8');
mb_http_output('utf-8');
function add($x, $y)
{
return (int)$x + (int)$y;
}
function addByArray($vars)
{
return array_sum($vars);
}
function hello($nm)
{
return 'こんにちは、' . $nm . ' さん!';
}
function helloByObj($obj)
{
return 'こんにちは、<a href="' . $obj->url . '">' . $obj->name . '</a> さん!';
}
$server = new SoapServer(null, array('uri' => 'http://www.doyouphp.jp/xp/soap/'));
$server->addFunction('add');
$server->addFunction('addByArray');
$server->addFunction('hello');
$server->addFunction('helloByObj');
$server->handle();
?>
説明するほどのものでもないですが、「サービス用関数で定義し、それをSoapServerオブジェクトに追加していく」といった手順になります。それぞれのサービスに相当する関数は全くひねりも何もないソースですね。。。ちなみに、SOAPメッセージのエンコーディングはutf-8になりますので、マルチバイト文字列を使用する可能性がある場合は結果をutf-8に変換する必要があります。今回のサンプルではmb_convert_encoding関数をあちこちに書きたくなかった(手抜き)ため、
- ソースのエンコーディングをutf-8
- 内部エンコーディングをutf-8(php.iniの設定はeuc-jp)
- 出力エンコーディングをutf-8(php.iniの設定はsjis)
としています。
また、SoapServerクラスではWSDLを生成する機能は持っていないようです。残念。。。
一方、これに対するクライアントですが、以下のような感じになります。
●SoapClient_test.php
<?php
echo phpversion();
?>
<hr>
<?php
function showTrace($result, $client)
{
echo '<h1>result=' . mb_convert_encoding(
$result, mb_internal_encoding(), 'utf-8')
. '</h1><br/>';
echo "●REQUEST:<br/><pre>"
. $client->__getLastRequestHeaders()
. mb_convert_encoding(
htmlspecialchars(
mb_ereg_replace("><", ">\n<", $client->__getLastRequest())),
mb_internal_encoding(), 'utf-8')
. "</pre>";
echo "●RESPONSE:<br/><pre>"
. $client->__getLastResponseHeaders()
. mb_convert_encoding(
htmlspecialchars(
mb_ereg_replace("><", ">\n<", $client->__getLastResponse())),
mb_internal_encoding(), 'utf-8')
. "</pre><hr/>";
}
?>
<?php
$location = 'http://www.doyouphp.jp/xp/soap/SoapServer_test.php5';
$uri = 'http://www.doyouphp.jp/xp/soap/';
try {
$client = new SoapClient(
null,
array(
'location'=> $location,
'uri' => $uri,
'trace' => 1 ));
$result = $client->add(3, 5);
showTrace($result, $client);
$result = $client->addByArray(array(1, 3, 5, 9));
showTrace($result, $client);
$result = $client->hello("Hideyuki Shimooka");
showTrace($result, $client);
$result = $client->hello(mb_convert_encoding("ソフト", 'utf-8'));
showTrace($result, $client);
$user = new stdClass();
$user->name = mb_convert_encoding("はろーわーるど", 'utf-8');
$user->url = "http://www.doyouphp.jp/";
$result = $client->helloByObj($user);
showTrace($result, $client);
}
catch (Exception $e) {
showTrace(null, $client);
echo '<pre>';
var_dump($e);
echo '</pre>';
exit;
}
?>
<hr>
<?php
show_source($_SERVER['SCRIPT_FILENAME']);
?>
実際の動作はEXPERIENCEのページで確認できるようにしましたのでどうぞ。また、上記サンプルを適当な名前を付けて保存し実行してもOKです。なお、Proxyサーバ経由でのアクセスの場合、
$client = new SoapClient(
null,
array(
'location'=> $location,
'uri' => $uri,
'trace' => 1 ));
を
$client = new SoapClient(
null,
array(
'location'=> $location,
'uri' => $uri,
'trace' => 1, 'proxy_host' => 'proxy_server.example.com',
'proxy_port' => 8080
));
のようにProxyサーバのIPアドレス or ホスト名とポート番号を指定することでOKです。その他オプションについては、PHP日本語マニュアルを参照してください。
さて、「サービス用関数で定義し、それをSoapServerオブジェクトに追加していく」といった手順なんですが、サービスを提供するのがメソッドの場合でもOKです。以下は、ServeByClassクラスのauthenticate、validateUserの各メソッドをサービスとして提供するSOAP Serverの例です。実際の動作とクライアント側のコードはEXPERIENCEのページで確認してみてください。
●SoapServer_test2.php
<?php
mb_internal_encoding('utf-8');
mb_http_output('utf-8');
class ServeByClass
{
public function authenticate($id)
{
$user = new stdClass();
$user->id = $id;
$user->name = 'user_' . $id;
$user->isAuthenticated = true;
return $user;
}
public function validateUser($obj)
{
return ($obj->name == 'user_' . $obj->id);
}
}
$server = new SoapServer(null, array('uri' => 'http://www.doyouphp.jp/xp/soap/'));
$server->setClass('ServeByClass');
$server->handle();
?>
この場合、SoapServerクラスのsetClassメソッドでServeByClassクラスの全メソッドをサービスとして登録しています。なお、SoapServerクラスのaddFunctionメソッドとsetClassメソッドを同時に使用するとaddFunctionメソッドで追加したサービスが使用できなくなってしまいます。バグなのか仕様なのか。。。
ふふふ。。。またまたいろいろと遊べそうです(^-^;
|