Issues

ZF-6347: DefaultComplexType strategy doesn't support nillable class properties

Description

The {{DefaultComplexType}} WSDL strategy only uses the first type declared in the {{@var}} docblock of a class property. Suppose the following docblock:


/** @var int|null My nillable integer variable */
public $myvariable;

In this case the variable is not considered nillable and a C# client (for example) will use the "int" type (which cannot be null) instead of "int?" (which can be null). There is sometimes a big difference between "0" and "null" for certain fields, especially booleans where null could mean "undefined".

Of course the following case also causes problems with the current code:


/** @var null|int My nillable integer variable */
public $myvariable;

Only the "null" type would be taken into account, and, well, this is not a type.

Comments

This patch fixes the issue by adding the {{nillable}} attribute to the {{element}} node when "null" is present among the {{@var}} types. The first non-null type is used for the {{type}} attribute.

Wouldn't this only fix nillable complex types? What if you wanted to make a string member var null, like so:

/** @var string|null Some var... */
public $some_var;

The {{DefaultComplexType}} strategy, at least in my usage experience, doesn't handle those, as {{Zend_Soap_Wsdl}} does instead.

String member variables can also be null. Actually, it works with any type, and for example I use {{string}}, {{int}} and {{bool}} nillable class properties in a personal project.

{{DefaultComplexType}} iterates over the class properties, detects the "null" (with my patch), and then calls {{$this->getContext()->getType()}}. So getting the type goes back to Zend_Soap_Wsdl, yes, but only after detecting "null". Whether the actual type is a native type handled by Zend_Soap_Wsdl directly, or a complexType handled by a strategy, doesn't matter :)

Does this apply to class methods and functions as well, or would this be an issue of AutoDiscover?

This only applies to class properties (variables).

For class methods, you can make parameters optional (nillable) by giving them a null default value. This would only work with ZF 1.9 and the document/literal style though, as the rpc style doesn't let you use nillable parts. See ZF-6349 and ZF-6351.

Very helpful, thank you.

The .diff file, when applied to Zend_Soap_Wsdl_Strategy_DefaultComplexType, worked for me. Because Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex extends the "DefaultComplexType" strategy, it too correctly picked up on the following php docblock:

@var string|null

...And made the variable "nillable"

Thanks!

PS - Any chance this fix can be applied to the trunk?

I think that this issue was fixed in trunk by [~rquadling] see ZF-10153.

My patch works by relying on a default value not being set for the property, rather than examining the different @var values.

e.g.

/** * Date Added * * @var xsd:datetime */ public $DateAdded;

becomes ...

in the wsdl file.

This is working for me (PHP) and my client's client (.NET based - I've no idea about their code).

Everyone happy.

And if you are wondering how xsd:datetime is working, I've made another patch to the AutoDiscovery code to allow for standard XSD types to be declared. Not 100% of them, but those I use.

I don't enough about getting my patches released, so hopefully someone can review them and make suggestions.

If I wrote:

class MyClass{ /* * @var xsd:dateTime */ public $myProp;

}

I obtain an error, while if I write:

class MyClass{ /* * @var dateTime */ public $myProp;

}

in wsdl I read "complex object" with namespase tns and not xsd. Why? How do I do for resolve this problem? thanks

If I wrote:

class MyClass{ /* * @var xsd:dateTime */ public $myProp;

}

I obtain an error, while if I write:

class MyClass{ /* * @var dateTime */ public $myProp;

}

in wsdl I read "complex object" with namespase tns and not xsd. Why? How do I do for resolve this problem? thanks