PHPの組み込みのSoapServer
を使用して2つの異なる配列を含む応答を返す際に問題があります。私のfruit
とvegetables
の配列は重複しているとPHPは思っています(そうではありません)。このレスポンスでは、Wrapper
クラスを使用して、PHPの__get()
という魔法のオーバーロードメソッドを使用しています。これは問題の一部であると思われます。PHP 7.x SoapServerが重複しない配列に対してXML参照(href = "#ref1"など)を返すのはなぜですか?
私のコードは、5.3、5.4、5.5および5.6のPHPのバージョンでは完全に正常に動作し、正しいSOAP XML応答を生成します。
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/">
<SOAP-ENV:Body>
<ns1:fooResponse>
<result>
<fruit>
<item>apple</item>
<item>orange</item>
<item>banana</item>
</fruit>
<vegetables>
<item>carrots</item>
<item>broccoli</item>
</vegetables>
</result>
</ns1:fooResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
まったく同じコードPHPのバージョン7.0、7.1および7.2RC2は以下を生成します
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://test-uri/">
<SOAP-ENV:Body>
<ns1:fooResponse>
<result>
<fruit id="ref1">
<item>apple</item>
<item>orange</item>
<item>banana</item>
</fruit>
<vegetables href="#ref1"/>
</result>
</ns1:fooResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
私の質問は、あるはなぜPHP 7.xのはfruits
を考えるとん:fruit
コレクションに戻って指し、vegetables
コレクション内の参照が含まれている予期しないXML、 vegetables
はまったく同じものなので、XML参照が返されますか? 7.xバージョンで動作が変わるのはなぜですか?ラッパークラスと__get()
メソッドの使用を継続し、以前のバージョンのPHPと同じ応答を実現するにはどうすればよいですか?
これは、私の検証可能な例です。一つのPHPファイルに含まれています。コマンドライン(不要Webサーバ)から直接実行することができます:
$wsdl = <<<WSDL
<?xml version="1.0" encoding="utf-8"?>
<definitions name="SoapArrayTest"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns="http://test-uri/"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/"
targetNamespace="http://test-uri/"
>
<types>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://test-uri/">
<complexType name="Baz">
<sequence>
<element name="fruit" type="tns:StringArray"/>
<element name="vegetables" type="tns:StringArray"/>
</sequence>
</complexType>
<element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="BazElement" type="tns:Baz"/>
<complexType name="StringArray">
<sequence>
<element name="item" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
<element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="StringArrayElement" type="tns:StringArray"/>
</schema>
</types>
<message name="fooRequest">
</message>
<message name="fooResponse">
<part name="result" type="tns:Baz"/>
</message>
<portType name="TestPortType">
<operation name="foo">
<input message="tns:fooRequest"/>
<output message="tns:fooResponse"/>
</operation>
</portType>
<binding name="TestBinding" type="tns:TestPortType">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="foo">
<soap:operation soapAction="#foo" style="rpc"/>
<input />
<output >
<soap:body parts="result" use="literal" namespace="http://test-uri/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</output>
</operation>
</binding>
<service name="TestService">
<port name="TestPort" binding="tns:TestBinding">
<soap:address location="http://example.com"/>
</port>
</service>
</definitions>
WSDL;
class Wrapper
{
private $object;
public function __construct($object)
{
$this->object = $object;
}
public function __get($property)
{
$value = $this->object->$property;
return $value;
}
}
function foo()
{
$baz = new stdClass();
$arr1 = array("apple", "orange", "banana");
$baz->fruit = $arr1;
$arr2 = array("carrots", "broccoli");
$baz->vegetables = $arr2;
$bar = new Wrapper($baz);
return $bar;
}
$fname = tempnam (__DIR__, "wsdl");
$f = fopen($fname,"w");
fwrite($f,$wsdl);
fclose($f);
$server = new SoapServer($fname, array('cache_wsdl' => WSDL_CACHE_NONE, 'soap_version' => SOAP_1_1));
$server->addFunction("foo");
$soapRequest = <<<XML
<?xml version="1.0" encoding="utf-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="blah" 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/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<ns1:foo>
</ns1:foo>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
XML;
$server->handle($soapRequest);
更新:
- この同様の質問PHP SoapClient creating XML references for identical elements, makes it unacceptable for serviceに対する解決策は動作しません。私の要素は同じではありません。私の要素が同じであれば、私はXMLの参考文献でOKです。
- 、2つの別々の
StringArray
構造を含むようにWSDLを変更すると、私は(それが動作しませんでした)このように私の配列に「アイテム」を追加しようとした を動作しません:
function foo() { $baz = new stdClass(); $fruits = array("item" => array("apple", "orange", "banana")); $baz->fruit = $fruits; $veggies = array("item" => array("carrots", "broccoli")); $baz->vegetables = $veggies; $bar = new Wrapper($baz); return $bar; }
私ができます私はこれで満足していないが
function foo() { $baz = new stdClass(); $fruits = new stdClass(); $fruits->item = array("apple", "orange", "banana"); $baz->fruit = $fruits; $veggies = new stdClass(); $veggies->item = array("carrots", "broccoli"); $baz->vegetables = $veggies; $bar = new Wrapper($baz); return $bar; }
:このような
item
プロパティを持つオブジェクトを使用してPHP 7.xで問題を修正。 PHP 7.xで配列を使うのがなぜうまくいかないのかまだ分かりません。
、あなたはそれを使用していますか? $ classmap = array( '会議' => '会議'); $ server = new SoapServer( 'soap。wsdl '、array(' classmap '=> $ classmap)); $ server-> setClass( "MySoapServer"); $ server-> handle(); – Marco
'stdClass'またはclassmapオプションのクラスを使用すると、問題はなくなります(質問の最新の更新を参照)。問題は、オブジェクトの代わりに配列が使用されている場合です。なぜ、5.xで動作するのか、7.xでは動作しないのかを知る必要があります。たぶん私のコードが壊れていて、PHP 5.xがもっと寛容でした。 –
それはもっと寛容だったからですが、PHPには多くの特徴が書かれていません。あなたは私の他の答えを試しましたか?私はこれが原因だと思います、あなたはそれをテストできますか? – Marco