Extensions are not generated as classes that extend another class
Bug Report
| Q | A |
|---|---|
| BC Break | yes/no |
| Version | x.y.z |
Summary
When a named type should extend another named-type, the generated php class does not extend.
Current behavior
When you have a WSDL as below, the generated class EntityTypeGetAllResult does not extend the PvApiResult class.
<s:complexType name="EntityTypeGetAllResult">
<s:complexContent mixed="false">
<s:extension base="tns:PvApiResult">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="EntityTypes" type="tns:ArrayOfPvEntityTypeData"/>
</s:sequence>
</s:extension>
</s:complexContent>
</s:complexType>
This generates the EntityTypeGetAllResult class, that does extend nothing.
An example of how the currently generated code can be found below:
<?php
namespace PerSaldo\Connectors\PerfectView\Client\Type;
class EntityTypeGetAllResult
{
/**
* @var \PerSaldo\Connectors\PerfectView\Client\Type\ArrayOfPvEntityTypeData
*/
private $EntityTypes;
/**
* @return \PerSaldo\Connectors\PerfectView\Client\Type\ArrayOfPvEntityTypeData
*/
public function getEntityTypes()
{
return $this->EntityTypes;
}
/**
* @param \PerSaldo\Connectors\PerfectView\Client\Type\ArrayOfPvEntityTypeData $EntityTypes
* @return EntityTypeGetAllResult
*/
public function withEntityTypes($EntityTypes)
{
$new = clone $this;
$new->EntityTypes = $EntityTypes;
return $new;
}
}
How to reproduce
https://api.perfectview.nl/perfectview.asmx?WSDL
Use this WSDL to generate types with the soap-client generate:types command.
My configuration is just as it was simply generated with the wizard:
use Phpro\SoapClient\CodeGenerator\Assembler;
use Phpro\SoapClient\CodeGenerator\Rules;
use Phpro\SoapClient\CodeGenerator\Config\Config;
use Phpro\SoapClient\Soap\Driver\ExtSoap\ExtSoapOptions;
use Phpro\SoapClient\Soap\Driver\ExtSoap\ExtSoapEngineFactory;
return Config::create()
->setEngine($engine = ExtSoapEngineFactory::fromOptions(
ExtSoapOptions::defaults('https://api.perfectview.nl/perfectview.asmx?WSDL', [])
->disableWsdlCache()
))
->setTypeDestination('themes/theme-name/_generated/PerfectView/Type')
->setTypeNamespace('ThemeName\Connectors\PerfectView\Client\Type')
->setClientDestination('themes/theme-name/_generated/PerfectView')
->setClientName('PerfectViewClient')
->setClientNamespace('ThemeName\Connectors\PerfectView\Client')
->setClassMapDestination('themes/theme-name/_generated/PerfectView')
->setClassMapName('PerfectViewClassmap')
->setClassMapNamespace('ThemeName\Connectors\PerfectView\Client')
->addRule(new Rules\AssembleRule(new Assembler\GetterAssembler(new Assembler\GetterAssemblerOptions())))
->addRule(new Rules\AssembleRule(new Assembler\ImmutableSetterAssembler(
new Assembler\ImmutableSetterAssemblerOptions()
)))
->addRule(
new Rules\IsRequestRule(
$engine->getMetadata(),
new Rules\MultiRule([
new Rules\AssembleRule(new Assembler\RequestAssembler()),
new Rules\AssembleRule(new Assembler\ConstructorAssembler(new Assembler\ConstructorAssemblerOptions())),
])
)
)
->addRule(
new Rules\IsResultRule(
$engine->getMetadata(),
new Rules\MultiRule([
new Rules\AssembleRule(new Assembler\ResultAssembler()),
])
)
)
;
Expected behavior
When you have a WSDL as below, the generated class EntityTypeGetAllResult should extend the PvApiResult class.
<s:complexType name="EntityTypeGetAllResult">
<s:complexContent mixed="false">
<s:extension base="tns:PvApiResult">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="EntityTypes" type="tns:ArrayOfPvEntityTypeData"/>
</s:sequence>
</s:extension>
</s:complexContent>
</s:complexType>
This should generates the EntityTypeGetAllResult class, that does extend the PvApiResult class.
An example of how the generated code shold be can be found below:
<?php
namespace PerSaldo\Connectors\PerfectView\Client\Type;
class EntityTypeGetAllResult extends PvApiResult
{
/**
* @var \PerSaldo\Connectors\PerfectView\Client\Type\ArrayOfPvEntityTypeData
*/
private $EntityTypes;
/**
* @return \PerSaldo\Connectors\PerfectView\Client\Type\ArrayOfPvEntityTypeData
*/
public function getEntityTypes()
{
return $this->EntityTypes;
}
/**
* @param \PerSaldo\Connectors\PerfectView\Client\Type\ArrayOfPvEntityTypeData $EntityTypes
* @return EntityTypeGetAllResult
*/
public function withEntityTypes($EntityTypes)
{
$new = clone $this;
$new->EntityTypes = $EntityTypes;
return $new;
}
}
Ext-soap does not provide that information: https://bugs.php.net/bug.php?id=45404
This issue has been reported a few times: #311, #291, #156, #144 ...
The solution is by adding a manual configuration that points out which classes need to extend from which classes by using the extend assembler: https://github.com/phpro/soap-client/blob/master/docs/code-generation/assemblers.md#extendassembler
Until we have a better way of getting the data back from the WSDL, there is no simple solution for this.
(Reopened this one in order to add a documentation to the known limitations page)
Hi @veewee ,
Thank you for the quick response! I'll try to use the ExtendAssembler to fix the issue for me.
Hello,
We noticed this issue got reported many times and want to tackle it at its core! Therefore, we've planned a project that will work on better types support. It’s going to be a huge project, so we are looking for ways to make development possible during our business hours instead of in our developers precious spare time.
In case you want this feature as badly as us: find out how you can support this project here 💚!
Closing this one - will be dealt with in #464