PHP5 namespaces result in invalid WSDL type name when implementing web service

I am trying to implement a SOAP server using the Zend_Soap_Server class in PHP.

Here is the webservice.php file, which is the entry point of the request:

 <?php require_once 'library.php'; require_once 'Zend/Loader/Autoloader.php'; $autoloader = \Zend_Loader_Autoloader::getInstance(); class Math { /** * This method takes ... * * @param integer $inputParam * @return \Library\IncrementedInt */ public function increment($inputParam) { return new \Library\IncrementedInt($inputParam); } } $options = array('uri' => 'http://localhost' . $_SERVER['REQUEST_URI']); if (isset($_GET['wsdl'])){ $server = new Zend_Soap_AutoDiscover(); $server->setClass('Math'); } else { $server = new Zend_Soap_Server(null, $options); $server->setClass('Math'); $server->setObject(new Math()); } $server->handle(); 

And I have a library.php file as follows:

 <?php namespace Library; class IncrementedInt { public $original; public $incremented; public function __construct($num) { $this->original = $num; $this->incremented = ++$num; } } 

Calling http://localhost/webservice.php?wsdl causes the output:

 <definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://localhost/webservice.php" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" name="Math" targetNamespace="http://localhost/webservice.php"> <script/> <types> <xsd:schema targetNamespace="http://localhost/webservice.php"> <xsd:complexType name="\Library\IncrementedInt"> <xsd:all/> </xsd:complexType> </xsd:schema> </types> <portType name="MathPort"> <operation name="increment"> <documentation>This method takes ...</documentation> <input message="tns:incrementIn"/> <output message="tns:incrementOut"/> </operation> </portType> <binding name="MathBinding" type="tns:MathPort"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="increment"> <soap:operation soapAction="http://localhost/webservice.php#increment"/> <input> <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/webservice.php"/> </input> <output> <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/webservice.php"/> </output> </operation> </binding> <service name="MathService"> <port name="MathPort" binding="tns:MathBinding"> <soap:address location="http://localhost/webservice.php"/> </port> </service> <message name="incrementIn"> <part name="inputParam" type="xsd:int"/> </message> <message name="incrementOut"> <part name="return" type="tns:\Library\IncrementedInt"/> </message> </definitions> 

Now, to test the functionality, I use soapUI 4.5.1 , which is a Java application that implements a SOAP client. Providing the URI http://localhost/webservice.php?wsdl should result in the extraction of the increment function, but this will not happen. Instead, it raises an error: The Value '\Library\IncrementInt' is an invalid name . It seems to me that it has a problem accepting \ as part of the type name. PHP, on the other hand, cannot do without them.

To make sure everything else is fine, I tested the same files without a namespace, and it runs smoothly.

Has anyone encountered a similar problem and, more importantly, does anyone know how to overcome this problem?

[UPDATE]

I managed to test the same script with ZF2 and it works. I may have to abandon the ZF1!

+6
source share
2 answers

The object type XSD \Library\IncrementedInt not a PHP class in the PHP namespace, as you specify:

 <?php namespace Library; class IncrementedInt { ... 

Actual type prefix:

 tns:\Library\IncrementedInt 

And remember tns: in front, which is a prefix. You cannot express this in PHP, which becomes even clearer when you extend it to a namespace URI:

 {http://localhost/webservice.php}\Library\IncrementedInt 

Zend SOAP also occurs from time to PHP Namespaces (PHP 5.2), so for an alias of this type you need to use a different strategy for the type PHP (class name). It takes a local type name:

 \Library\IncrementedInt 

And replaces each "invalid" character with this underscore type:

 _Library_IncrementedInt 

Therefore, you need to name the class this way:

 <?php class _Library_IncrementedInt { ... 

If you want it to work out of the box.


Then you asked using comments to clarify:

So you say that I can’t do anything to have a class with names as a type name, right?

Well, as for the default behavior, most likely not, however, since the term "Strategy" is used, I would say that there is some mechanism for extending the Zend Soap for this operation and injecting another that, for example, allows the use of names classes (classes by their FQCN), see Strategy Template .

And if it's just one class, you can do some cheap trick at the same time and expand your class with names like a short name or an alias using class_alias .

+4
source

Zend_Soap_AutoDiscover accepts the type name from the phpdoc block, i.e. from this comment line:

 * @return \Library\IncrementedInt 

You can simply change this type, for example, IncrementedInt , without a namespace or slash.

+1
source

Source: https://habr.com/ru/post/952423/


All Articles