PHP と SOAP

PHP から SOAP 経由でサービスをよんでね」とか言われたのですが,PHP は使ったことがないのですよ...orz


とりあえず調べてみると,PEAR にベータ版だが SOAP モジュールがあるのでこれを使うことにします.
基本的な使い方は以下のサイトで紹介されています.


ただねー,「これ使って」と渡された WSDL ファイルを SOAP_WSDL が正しく解釈してくれない...orz
どっちが悪いんだろうか.

仕方がないので SOAP_Client の方でがんばることに.

ヘッダに情報を追加する

Client.php や Value.php あたりのコードを読んで「こんな感じか?」と作ってみた.

<?php
require_once('SOAP/Client.php');

$client = new SOAP_Client('http://localhost:8080');

$header = new SOAP_Header(
    '{http://www.example.com}aaa',
    false,
    new SOAP_Value(
        '{http://www.example.com}bbb',
        'string',
        'text-value'
    )
);
$client->addHeader($header);

$method = new SOAP_Value(
    '{http://www.example.com/method}hoge',
    false,
    array(
        'arg0' => 'hello!',
        'arg1' => 1234
    )
);

$options = array(
    'style' => 'document',
    'timeout' => 20
);

$res = $client->call(
    'hoge',
    array('hoge' => $method),
    $options
);

print_r($res);
?>


↓生成された SOAP リクエスト

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
        xmlns:ns4="http://www.example.com"
        xmlns:ns5="http://www.example.com/method"
        SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <SOAP-ENV:Header>
        <ns4:aaa xsi:type="xsd:string"
                SOAP-ENV:actor="http://schemas.xmlsoap.org/soap/actor/next"
                SOAP-ENV:mustUnderstand="0">
            <ns4:bbb xsi:type="xsd:string">text-value</ns4:bbb>
        </ns4:aaa>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <ns5:hoge>
            <arg0 xsi:type="xsd:string">hello!</arg0>
            <arg1 xsi:type="xsd:int">1234</arg1>
        </ns5:hoge>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

複雑な引数に対応する

いろいろ実験してみる.

<?php
require_once('SOAP/Client.php');

$client = new SOAP_Client('http://localhost:8080');

$ns = '{http://www.example.com/method}';
$arg0 = new SOAP_Value(
    $ns . 'arg0',
    'string',
    'hello!'
);
$arg1 = new SOAP_Value(
    $ns . 'arg1',
    false,
    array(
        'item1' => new SOAP_Value(
            $ns . 'item1',
            $ns . 'MyType', // ←ここはオリジナルタイプ
            array(
                'value' => new SOAP_Value(
                    $ns . 'value',
                    'string',
                    'ほげ'
                )
            )
        ),
        'item2' => new SOAP_Value(
            $ns . 'item2',
            'string',
            'HOGE'
        )
    )
);

$method = new SOAP_Value(
    $ns . 'hoge',
    false,
    array(
        'arg0' => $arg0,
        'arg1' => $arg1
     )
);

$options = array(
    'style' => 'document',
    'timeout' => 20
);

$res = $client->call(
    'hoge',
    array('hoge' => $method),
    $options
);

print_r($res);
?>

↓生成された SOAP リクエスト

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
        xmlns:ns4="http://www.example.com/method"
        SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <SOAP-ENV:Body>
        <ns4:hoge>
            <ns4:arg0 xsi:type="xsd:string">hello!</ns4:arg0>
            <ns4:arg1>
                <ns4:item1 xsi:type="ns4:MyType">
                    <ns4:value xsi:type="xsd:string">ほげ</ns4:value>
                </ns4:item1>
                <ns4:item2 xsi:type="xsd:string">HOGE</ns4:item2>
            </ns4:arg1>
        </ns4:hoge>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

自動変換(するはず)

テストしてないので注意!


http://www.pear.php.net/package/SOAP/docs/latest/__filesource/fsource_SOAP__SOAP-0.12.0exampleclient.php.html
を読んでたら「できそうだ」ということがわかった.でもテストしていない.


レスポンスを受けたとき,登録したタイプの要素が含まれていると,デコードした値を対応するクラスのオブジェクトに詰めてくれるっぽい.

http://www.pear.php.net/package/SOAP/docs/latest/__filesource/fsource_SOAP__SOAP-0.12.0Base.php.html
↑の _decode あたり.

<?php
require_once('SOAP/Value.php');

function A_Type_QName() {
    return '{http://www.example.com/type}A_Type';
}

class A_Type {
    var $path;
    var $list;

    function __construct($path, $list) {
        $this->path = $path;
        $this->list = $list;
    }

    function toSoap($top) {
        $ns = '{http://www.example.com/type}';
        $soap = new SOAP_Value(
            $top,
            A_Type_QName(),
            array(
                'path' => new SOAP_Value(
                    $ns . 'path',
                    'string',
                    $this->path
                ),
                'list' => new SOAP_Value(
                    $ns . 'list',
                    'array',
                    $this->list
                )
            )
        );

        return $soap;
    }
}
?>
<?php
require_once('SOAP/Client.php');
require_once(dirname(__FILE__) . '/a_type.php');

$client = new SOAP_Client('http://localhost:8080');
$client->_auto_translation = true;
$client->setTypeTranslation(A_Type_QName(), 'A_Type');

$a_type = new A_Type(
    '/var/www/html/a_type.php',
    array(
        'name' => 'hoge',
        'id' => 1234,
        'description' => 'foo'
    )
);

$ns = '{http://www.example.com/method}';
$methodName = 'ope1';

$method = new SOAP_Value(
    $ns . $methodName,
    false,
    array('arg0' => $a_type->toSoap($ns . 'arg0'))
);

$res = $client->call(
    $methodName,
    array($methodName => $method),
    array(
        'style' => 'document',
        'timeout' => 20
    )
);
print_r($res);
?>
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
        xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
        xmlns:ns4="http://www.example.com/type"
        xmlns:ns5="http://www.example.com/method"
        SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
    <SOAP-ENV:Body>
        <ns5:ope1>
            <ns5:arg0 xsi:type="ns4:A_Type">
                <ns4:path xsi:type="xsd:string">/var/www/html/a_type.php</ns4:path>
                <ns4:list>
                    <name xsi:type="xsd:string">hoge</name>
                    <id xsi:type="xsd:int">1234</id>
                    <description xsi:type="xsd:string">foo</description>
                </ns4:list>
            </ns5:arg0>
        </ns5:ope1>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>