soap-client icon indicating copy to clipboard operation
soap-client copied to clipboard

Support types in multiple namespaces

Open mtouellette opened this issue 9 months ago • 9 comments

Feature Request

Support types in multiple namespaces.

Q A
New Feature yes
RFC no
BC Break yes

Summary

A SOAP type of a given name would have multiple class type files and classmap entries via clark notation supported in php 8.4.

mtouellette avatar Mar 19 '25 18:03 mtouellette

Can you elaborate what you are expecting exactly? I'm a bit confused by your description.

veewee avatar Mar 19 '25 19:03 veewee

Sure. I'm not 100% this is doable given the historic limitations of the soap extension, however, it seems possible in theory.

For a given type that appears in two different namespaces, lets say AccidentItem

<xs:schema xmlns:tns="http:\schemas.acme.com\app\sdk\2014\11_account_policy_canadiancommercialauto_driver_drivernu" ...>

<xs:complexType name="AccidentItems">
  <xs:sequence>
    <xs:element minOccurs="0" maxOccurs="unbounded" name="AccidentItem" nillable="true" type="tns:AccidentItem"\>
  <\xs:sequence>
<\xs:complexType>

<xs:schema xmlns:tns="http:\schemas.acme.com\app\sdk\2014\11_account_policy_canadiancommercialauto_driver_drivernt" ...>

<xs:complexType name="AccidentItems">
  <xs:sequence>
    <xs:element minOccurs="0" maxOccurs="unbounded" name="AccidentItem" nillable="true" type="tns:AccidentItem"\>
  <\xs:sequence>
<\xs:complexType>

Two different class type files would be created, each under a different namespace based off the schema. Maybe something like so...

type folders
	http\
		schemas\
			acme\
				com\
					app\
						sdk\
							2014\
								11\
									_account\
										_policy\
											_canadiancommercialauto\
												_driver\
													_drivernt\
														AccidentItem.php
													
													_drivernu\
														AccidentItem.php

continued...

mtouellette avatar Mar 19 '25 20:03 mtouellette

In the php files

  <?php
    
    namespace MyNamespace\http\schemas\acme\com\epic\sdk\2014\11\_account\_policy\_canadiancommercialauto\_driver\_drivernt;
    
    class AccidentItem
    {
  <?php
  
    namespace MyNamespace\http\schemas\acme\com\epic\sdk\2014\11\_account\_policy\_canadiancommercialauto\_driver\_drivernu;
    
    class AccidentItem
    {

Then in the classmap, clark notation (https://www.php.net/manual/en/migration84.new-features.php) would be used to map them

...
new ClassMap('{http:\\schemas.acme.com\app\sdk\2014\11\_account\_policy\_canadiancommercialauto\_driver\_drivernt}AccidentItem', \MyNamespace\http\schemas\acme\com\epic\sdk\2014\11\_account\_policy\_canadiancommercialauto\_driver\_drivernt\AccidentItem::class),
new ClassMap('{http:\\schemas.acme.com\app\sdk\2014\11\_account\_policy\_canadiancommercialauto\_driver\_drivernu}AccidentItem', \MyNamespace\http\schemas\acme\com\epic\sdk\2014\11\_account\_policy\_canadiancommercialauto\_driver\_drivernu\AccidentItem::class),

mtouellette avatar Mar 19 '25 20:03 mtouellette

Thanks for sharing ! I totally forgot that feature was added to PHP 8.4.

Since version 4, we moved away from using PHP's soap extension and instead are using our own encoding system. This system already supports having a PHP class per namespace::type, just like PHP 8.4 does.

I think the only thing is missing in here, is making code generation segment types per namespace, which rises some problems that need to be solved:

The namespace naming strategy you describe here is something I don't really like : using the XML namespace to generate PHP namespaces is doomed to be confusing. Another approach could be to provide a namespace map that links an XML namespace to a PHP namespace. But this would mean you need to already be quite familiar with the webservice in order to get good results. It would rather be an opt-in feature on top of what we already have, meaning we would still need to remain the logic for combining types but making them aware of the type's PHP namespace. Since we know all the namespaces in the WSDL already, we could generate a map like this given a strategy to map them. That would make it possible to generate something like you suggested or fine-tune it to your own needs.

Currently the code generation is the oldest part of this codebase. It currently operates on one specific type, but doesn't have a lot of context about other types. This makes it hard to know where the PHP namespaces of other types are located. So I think a first step in order to achieve this, would be making the code generation more context-aware.

Another I think of, is anonymous named types: A complex type kan contain nested internal types with a specific name. Those types are now generated as stand-alone types, but it would mean that if 2 types define an internal type with the same name in the same namespace, only 1 class gets mapped again. Maybe for these situations, we could prefix the name of the type with the parent's type. Something like TheParentTypeChildType.

So to summarize : Yes it is surely possible since everything is already there, but it would be a quite some work (as in a couple of days) to get it done the right way. Is this something you would like to sponsor?

veewee avatar Mar 20 '25 06:03 veewee

The mapping method I suggested is rather cumbersome and can't say that I care for it myself. Java uses a similar method but I would definitely prefer something more concise. It was also pointed out to me that all numeric namespace segments are not valid. So there would definitely need to be some sort of mapping strategy. Given that there may edge cases and different user preferences it would great if there were some sort of injectable strategy via a closure or interface.

It is an interesting point you make about nested internal types. This sounds like a questionable WSDL design but in my experience they are all usually pretty bad as they tend to be generated as an afterthought. I enjoyed your slide deck by the way. Prefixing sounds good but again an injectable strategy would be great to allow for other options.

The fact that you are using your own encoding is quite impressive. I would still be interested in using the soap extension for performance reasons. Although I am certainly open to other options if they work and are reasonably performant.

As far as sponsorship goes, the company I work for is not very large and has not sponsored anything up to this point. It is something that some of the developers here discuss and we all seem to agree that the OSS developers really do deserve some level of compensation. For myself personally, the limitations of the php soap implementation have been a thorn in my side for years and would not be opposed to a one time donation. Although I doubt that what I am willing pay out of my pocket would be worth your time. I say this only because we do have a working solution that works quite well. Although the additional technologies required add to the complexity of maintaining the integration code and a php only solution would be nice. In any case I'll bring it up to management and see if they would be interested.

mtouellette avatar Mar 20 '25 18:03 mtouellette

The fact that you are using your own encoding is quite impressive. I would still be interested in using the soap extension for performance reasons. Although I am certainly open to other options if they work and are reasonably performant.

Of course, it is always slower than the extension because it isn't written in C. I did some benchmarks and, to me, the performance is still pretty good. Also in SOAP, the HTTP request itself is considerable slower than parsing the request / response. To give you an idea : We are currently using it in production on a big e-commerce website.

veewee avatar Mar 21 '25 06:03 veewee

Do not want to spoil the chances of this getting added, but this one is properly related to recognizing same types in diferent namespaces: https://github.com/phpro/soap-client/issues/577

func0der avatar Apr 22 '25 14:04 func0der

You are not spoiling any chances of it getting added. If you want to increase chances of it getting added, the same comment as above still applies:

So to summarize : Yes it is surely possible since everything is already there, but it would be a quite some work (as in a couple of days) to get it done the right way. Is this something you would like to sponsor?

veewee avatar Apr 23 '25 05:04 veewee