2016-11-18 3 views
1

Можно ли вызвать конструктор PHP SoapClient, который принимает URL-адрес в качестве аргумента, вместо содержимого строки.Вызов конструктора SoapClient с WSDL из переменной вместо URL-адреса

В моем примере у меня есть обработанный DOMDocument, содержащий WSDL, который я бы записал в строку с помощью saveXML().

Идея состоит в том, чтобы не трогать файловую систему, если это возможно. Я пробовал память php: //, но тесты при получении содержимого потока с такими функциями, как file_get_contents, приводят к пустым строкам, поскольку я подозреваю, что контекст потока исчез. Есть ли другой способ?

ответ

1

Да, можно создать экземпляр класса SoapClient с переменной, содержащей вашу WSDL строку, все , не прикасаясь к файловой системе. Поскольку SoapClient требует параметра URI, мы будем создавать Data URI и передать его в:

$wsdlstring = <<<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; 

$doc = new DOMDocument(); 
$doc->loadXML($wsdlstring); 
$data = $doc->saveXML(); 
$wsdl = 'data://text/plain;base64,'.base64_encode($data); 
$soapclient = new SoapClient($wsdl); 
var_dump($soapclient->__getFunctions()); 
+0

Это только кажется, что вызовет ошибку при создании экземпляра SoapClient: «не удалось открыть поток: rfc2397: нет запятой в URL» – Russ

+0

Я расширил ответ, чтобы предоставить рабочий образец, однако технически WSDL теперь находится в файловой системе внутри самого файла PHP. Однако, если WSDL был построен только с помощью вызовов метода DOMDocument, он будет полностью находиться в памяти. Когда я получу несколько минут свободного времени, я обновлю ответ, чтобы WSDL был построен «на лету», используя «DOMDocument». –

+0

Я думаю, что ключевым выводом здесь является то, что 'SoapClient' может принимать URL как аргумент, но можно передать содержимое строки, как задает вопрос, потому что PHP рассматривает его как контекст потока. Поэтому мы можем заменить в 'data: //' вместо 'file: //' или 'http: //' –