仕事でちょっと必要になったので、PHPのSOAP拡張モジュールを使ってみた。わかってしまえばなんということはないのだが、意外と資料が見当たらなかったので手順をメモしておく。

SOAPって何だ?

Simple Object Access Protocol

とくちょう:

  • 通信プロトコル : HTTP

  • SOAP 1.0 : HTTPのみ

  • SOAP 1.1~ : FTP、SMTPなども選択できる

    (現行バージョンは1.2)

  • データフォーマット : XML

  • 「エンベロープ」というメタデータでくるむ

  • 文書本体(Body)の前にヘッダ(Header)をつけることができる(=Optional)

PHPでSOAP

PHP5からSOAPの拡張モジュールは標準添付になっているが、ビルドオプションで利用を宣言する必要がある。

今回の目標

PHPによるwebアプリがクライアントになり、とあるサーバのサービスをSOAPで叩いて利用する。

インストール

configureオプションに「–enable-soap」を指定してビルド。

設定

パラメータの意味とデフォルトはこの辺に。今回はとりあえずなにも指定しない(=デフォルト値が使用される)状態で。

WSDL
WSDLとは?

Web Services Description Language

データの名前と型、サーバとやり取りするメッセージ、サービスの定義などのメタデータを記述したもの。サーバサイドでSOAPサービスを提供する場合は作成する必要があるが、既存のサービスを利用する場合は提供者が用意しているWSDLファイルを使えばいい。今回の案件でも用意されていた。

そのうち必要になりそうなので、この調査をしたときにヒットしたサイトもLinksにメモっておく。

実際のコード

「すでに提供されているAPIをPHPから使う」場合のサンプルがあまり見当たらなかったので、ここでは「要求されているSOAPメッセージ(XML)を生成するには」というアプローチで書いてみる。

サンプルXML

APIが「この機能を使うにはこんなSOAPメッセージを送れ」というXMLをサンプルとして公開している、と仮定する(…というか今回の案件では仕様書に書いてあった)。

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:ns1="http://www.example.com/SomeProcess">
  <env:Header>
    <ns1:AuthHeader>
      <ns1:Username>USERNAME</ns1:Username>
      <ns1:Password>PASSWORD</ns1:Password>
    </ns1:AuthHeader>
  </env:Header>
  <env:Body>
    <ns1:CreateSomeProcessRequest>
      <ns1:request>
        <ns1:SomeType>foo</ns1:SomeType>
        <ns1:SomeParam>bar</ns1:SomeParam>
        <ns1:SomeDetail>some parameter example</ns1:SomeDetail>
        <ns1:Entries>
          <ns1:SomeProcessRequestEntry>
            <ns1:Shortname>hoge</ns1:Shortname>
            <ns1:Url>http://www.exapmle.net/hoge</ns1:Url>
            <ns1:flag>true</ns1:flag>
          </ns1:SomeProcessRequestEntry>
          <ns1:SomeProcessRequestEntry>
            <ns1:Shortname>piyo</ns1:Shortname>
            <ns1:Url>http://www.exapmle.jp/piyo</ns1:Url>
            <ns1:flag>false</ns1:flag>
          </ns1:SomeProcessRequestEntry>
        </ns1:Entries>
      </ns1:request>
    </ns1:CreateSomeProcessRequest>
  </env:Body>
</env:Envelope>
サンプルコード

こんなコードでメッセージが生成できる。SOAPメッセージとの対比に気をつければ使い方が把握できると思う。

<?php
class SoapSample
{
    public function doSoapRequest()
    {
        // SoapClientの生成         $this->soap_client = new SoapClient(
            'http://www.example.com/path/to/wsdl_file.wsdl',
            array(
                'soap_version'  => SOAP_1_2,
                'trace'         => 1, // リクエスト / レスポンスのヘッダ / 本文を取得するために必要             )         ) ;         // 認証用ヘッダを生成して付与         $soap_header = array(
            'http://www.exapmple.com/SomeProcess', // 名前空間             'AuthHeader',                // 要素名             array(                       // パラメータの配列(SoapVar)                 'Username' => new SoapVar('USERNAME', XSD_STRING),
                'Password' => new SoapVar('PASSWORD', XSD_STRING),
            )
        ) ;

        $this->soap_client->__setSoapHeaders($soap_header) ;

        // リクエストパラメータを生成         $soap_param = array(
            'request' => array(
                'SomeType'      => 'foo',
                'SomeParam'     => 'bar',
                'SomeDetail'    => 'some parameter example',
                'Entries' => array(
                    array(
                        'Shortname' => 'hoge',
                        'Url'       => 'http://www.exapmle.net/hoge',
                        'flag'      => true,
                    )
                    array(
                        'Shortname' => 'piyo',
                        'Url'       => 'http://www.exapmle.jp/piyo',
                        'flag'      => false,
                    )
                )
            )
        ) ;

        // リクエストを行う         try         {             $this->soap_client->CreateSomeProcessRequest($soap_params) ;
        }
        catch (Exception $e)
        {
            echo $e ;
        }
    }
}
?>
リクエストとレスポンス

リクエスト / レスポンスのヘッダ / 本文はそれぞれSoapClientクラスのメソッドで取得できる。

レスポンスも当然XMLで返ってくるので、適当なライブラリでパーズして使う。

エラー処理

何らかの理由でエラーが発生した場合、以下のような構造のXMLが返ってくる。ざっくり要約すると「soap:Bodyにsoap:Faultメッセージが含まれていたらエラー」ということである。

<?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>
    <soap:Fault>
      <soap:Code>
        <soap:Value>soap:Receiver</soap:Value>
      </soap:Code>
      <soap:Reason>
        <soap:Text xml:lang="en">Server was unable to process request. ---> Exception thrown by  Authenticator.AuthenticateUser method. Authentication failed. The Username and/or Password are invalid. Please enter a valid Username and Password</soap:Text>
      </soap:Reason>
      <soap:Detail />
    </soap:Fault>
  </soap:Body>
</soap:Envelope>

soap:Faultメッセージの存在をチェックしてエラー処理をするとよいだろう。

まとめ

駆け足かつちょうざっくりの説明だが、とりあえずこれでクライアントとしてPHPからSOAPのwebAPIを叩くことはできるようになった。もしかしたらSOAPサーバもやるかもしれないが、予定は未定。

Glossary

SOAP (プロトコル) – Wikipedia

http://ja.wikipedia.org/wiki/SOAP_(%E3%83%97%E3%83%AD%E3%83%88%E3%82%B3%E3%83%AB)

SOAPとは 【Simple Object Access Protocol】 – 意味/解説/説明/定義 : IT用語辞典

http://e-words.jp/w/SOAP.html

WSDLとは 【Web Services Description Language】 – 意味/解説/説明/定義 : IT用語辞典

http://e-words.jp/w/WSDL.html

SOAP on PHP

PHP: SOAP 関数 – Manual

http://www.php.net/manual/ja/ref.soap.php

PHP5でSOAPを用いたブックマークサービスを作成する:CodeZine

http://codezine.jp/article/detail/199

PHP5を試してみる – SOAP extension+Google Web APIsでGoogle検索してみる – Do You PHP?

http://www.doyouphp.jp/php5/php5_soap_extension_google.shtml

SOAPの仕掛けはどうなっている?

http://www.atmarkit.co.jp/fxml/rensai/soap01/soap02.html