Doc->Bug #78749 [Ver]: Wrong error message when maxOccurs is exceeded
| From: | tony at marston-home dot demon dot co dot uk | Date: | Wed, 06 Nov 2019 10:30:39 +0000 |
| Subject: | Doc->Bug #78749 [Ver]: Wrong error message when maxOccurs is exceeded | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-223597@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=78749&edit=1
ID: 78749
User updated by: tony at marston-home dot demon dot co dot uk
Reported by: tony at marston-home dot demon dot co dot uk
-Summary: No comprehensive documentation on how SoapClient
serializes data per the WSDL
+Summary: Wrong error message when maxOccurs is exceeded
Status: Verified
-Type: Documentation Problem
+Type: Bug
Package: SOAP related
Operating System: Windows 10
PHP Version: 7.3.11
Block user comment: N
Private report: N
New Comment:
This is NOT a documentation error as your implementation clearly does NOT follow the WSDL
specification.
Previous Comments:
------------------------------------------------------------------------
[2019-11-06 10:23:09] tony at marston-home dot demon dot co dot uk
You may not be familiar with my use of a <contacts> element which is a container for 1 or more
<contact> elements, but if you look at the example XML document in http://www.w3.org/TR/xmlschema-0/#PO you will see
that it has an <items> element which is a container for one or more <item> elements.
The <items> element has an implied maxOccurs of 1, and in my test data my <contacts>
element has an explicit maxOccurs of 1. The <item> element has a maxOccurs of
"unbounded", and in my test data my <contact> element has a specified limit, and I
am testing to see what happens if the limit is exceeded when I supply 3 occurrences. If the
maxOccurs value is 1 the error message is wrong. If the maxOccurs value is 2 there is no error
message.
You said in your reply that "Currently PHP only really cares if maxOccurs>1 or not."
This is clearly wrong. The WSDL specification clearly states that the maxOccurs value defines
"The maximum number of times an element may appear" and as "1" is a valid value
the XML document should be validated to ensure that this limit is not violated. This is not an
optional piece of validation, it is REQUIRED.
------------------------------------------------------------------------
[2019-11-06 09:45:11] tony at marston-home dot demon dot co dot uk
It is clear that you do not understand the structure that I am using.
<contacts> is a container that can occur 0 or 1 times. It can contain a number of
<contact> elements (arrayOfContactInfo) which themselves are containers for other elements.
It is the value of maxOccurs for the <contact> element which is being problematic. Although my
data creates 3 occurrences I was testing to see what happens when I set maxOccurs to a smaller
value.
If I set it to 2 it does not complain that I have exceeded the maxOccurs value.
If I set it to 1 it does complain, but the error message is totally wrong.
The official specification at http://www.w3.org/TR/xmlschema-0/#OccurrenceConstraints
contains the sentence "The maximum number of times an element may appear is determined by the
value of a maxOccurs attribute in its declaration." Your code is clearly not validating the
maxOccurs value, therefore your code is not following the specification.
You say that the data does not *need* to be validated because the developer is supposed to know what
they're doing, but you are missing the whole point of WSDL/XSD/DTD validation which verifies
that the XML document which it is given conforms to the specified structure in order to trap any
mistakes made by the developer. It is supposed to guarantee that the XML document which is received
at the other end is exactly as expected. It does this by looking at the minOccurs and maxOccurs
value for each element. An element is optional if minOccurs is zero but required if it is greater
than zero. The specification also states that no element should occur more times than as stated in
the maxOccurs value. Your code is NOT doing this, therefore your code does NOT conform to the
specification.
------------------------------------------------------------------------
[2019-11-05 19:45:57] requinix@php.net
> It is a container for any number of <contact> elements,
Not according to the WSDLs. The one in your report very clearly says maxOccurs=1 and the one in your
download says maxOccurs=3.
Currently PHP only really cares if maxOccurs>1 or not. If it is then the value being serialized
is actually a list (ie, array) of values, who each are to be serialized individually. If you have
maxOccurs=1 for an object and pass a list then PHP will complain because the list doesn't have
attributes.
> The idea that the value of maxOccurs need not be validated is nonsense.
In the world of specifications there are two words with two different meanings: "need" and
"should".
The data does not *need* to be validated because the developer is supposed to know what they're
doing, and if they get it wrong then it's not like PHP can automatically recover. The data
*should* be validated because that's A Good Thing To Do.
PHP does not validate right now. *Should* it? Yes, so the developer can be presented with nicer
error messages and, as a more egregious example, not attempt to send invalid data to a service that
the client could have known was invalid. But does it *need* to? No, because when used correctly
ext/soap is perfectly capable of sending data in its current state.
Let me repeat that last sentence to emphasize why I'm making this a doc bug: ext/soap is
perfectly capable of sending data in its current state. When you passed a list of objects where the
WSDL specified one object, the mistake was on you. PHP could have given you a better error message
that more directly indicated the source of the problem, absolutely*, but that doesn't change
how PHP was not able to recover and somehow adapt the data to suit. You, the developer, would have
to go in and fix your code.
Now I really don't want this argument to turn into both of us repeating ourselves until the
other person gives up, so here's what you should do: since ext/soap does not currently attempt
to validate the data against the WSDL in any way, or even have the functionality to do so AFAIK, you
should *request* that validation be *added* so that developers like you and me could make use of it
and benefit from the failure messages it may produce. I would suggest that SoapClient gets a
"validate" (or perhaps "__validate") method that takes a function name and
parameters and validates, and/or that __soapCall() gets an option to opt-into validating before
sending.
* In case this is a source of confusion, I'm saying PHP could give a better message *in
principle*. The cause of your problem is PHP being given a list where it needs an object, but it
isn't discovering anything wrong until it reaches the point where it tries to serialize a
"first_name" property when it was working on an array with keys (0,1,2). With my quick
reading through the source, I don't believe that it *currently* can accurately report some sort
of "expecting object, received list" message at that point in the process - all it knows
there is that the array doesn't have the required key.
------------------------------------------------------------------------
[2019-11-05 18:45:24] tony at marston-home dot demon dot co dot uk
I disagree completely with your assessment.
In my WSDL the element <contacts> can occur 0 or 1 times. It is a container for any number of
<contact> elements, and each <contact> contains its own group of elements which can
occur 0 or 1 times each.
The idea that the value of maxOccurs need not be validated is nonsense. The official specification
at http://www.w3.org/TR/xmlschema-0/#OccurrenceConstraints
contains the sentence "The maximum number of times an element may appear is determined by the
value of a maxOccurs attribute in its declaration." To any reasonable person this would mean
that if the WSDL provides a value for maxOccurs then the XML document should checked to ensure that
this limit is not violated.
------------------------------------------------------------------------
[2019-11-05 17:52:19] requinix@php.net
Here's what is happening:
If maxOccurs is 1 then the PHP value should not be a list. Because there's only possibly one.
It doesn't make sense to have a list when there can only be a single entity/value in it. Like
having the title be an array("Title") is weird.
If maxOccurs is unbounded or >1, PHP does not validate against the count. It just doesn't.
If the max is 2 and you give 3 then it will put in all 3 (which you can verify through
__getLastRequest).
So there's two issues here:
1. That behavior is undocumented. I think it's the most important aspect of this report, so
I'm repurposing this as a doc bug.
2. The missing maxOccurs validation. I don't see this as high priority as it doesn't seem
that SoapClient has any particular intention to perform validation beyond what is required to
serialize the data to XML; maxOccurs when >1 isn't being validated, minOccurs when >1
isn't being validated, and there are probably other rules not being validated either.
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=78749
--
Edit this bug report at https://bugs.php.net/bug.php?id=78749&edit=1