According to the documentation, the constructor of classes mapped with the classmap
option of a SoapClient
is not called, but the magic methods __get()
and __set()
are.
I tried to use the __set()
magic method, however, I fail to make it happening. It looks like both constructor and magic method __set()
are ignored.
The type defined by the WSDL document:
<xsd:simpleType name="THpSvcWCleRubrique">
<xsd:restriction base="xsd:unsignedInt"/>
</xsd:simpleType>
...
<xsd:complexType name="THpSvcWTableauClesRubriques">
<xsd:sequence>
<xsd:element name="THpSvcWCleRubrique" type="hp:THpSvcWCleRubrique" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
The corresponding PHP class:
class THpSvcWTableauClesRubriques {
/** @var int[] */
private $THpSvcWCleRubrique;
public function __get($name) {
if ($name === "THpSvcWCleRubrique") {
return $this->THpSvcWCleRubrique;
}
}
public function __set($name, $value) {
if ($name === "THpSvcWCleRubrique") {
$this->THpSvcWCleRubrique = $value ?? [];
}
}
}
And the creation of the SoapClient
:
$this->soapClient = new SoapClient($this->url, [
"login" => $this->username,
"password" => $this->password,
"soap_version" => SOAP_1_2,
"features" => SOAP_SINGLE_ELEMENT_ARRAYS,
"classmap" => [
"THpSvcWTableauClesRubriques" => THpSvcWTableauClesRubriques::class
]
]);
My issue is that when there is no element in an array, the SOAP web service returns null
and I would like to interpret it as []
instead. Since the magic method is not called, I still have null
instead of []
.
Am I missing something? Or is there an option to make null
interpreted as []
?
The PHP version is 7.3.7.
2
Answers
I couldn't make it work with the
__set()
magic method.So here is what I did as a somewhat answer: overriding the PHP
SoapClient
to inject some business logic after construction of SOAP entities.The custom SOAP client:
Entities needing after construction logic may implement
SoapEntity
:Usage:
This answer is just to bring some clarity to the topic of soap and PHP. The documentation is often a little unclear at this point.
With PHP 8 you can use typed class properties with default values. Just have a look at the following example:
Or even quicker just use property promotion constructors …
Both variants declare
$integerCollection
as array. So even the declared type in the WSDL isminOccurs="0"
and therefor optional, the PHP data object property will still be an array.You have to know, that the PHP soap client never calls a constructor. It uses
__get()
and__set()
if there is no class property, which is not named exactly like a complex type element definition from this class. If the PHP class has a property which maches the name directly, the magic methods won ‘t be called.To interpret single values (null is in this context a single value) as an array, just initialize the soap client with the following option: