If you are thinking of writing a web service or a client based on a WSDL, you can easily generate the code for PHP or any other language using tools likes wsdl2php or other wsdl2xxx category tools. Then you don’t need to really worry about what is the schema of the WSDL or any other finer details. But sometime it may useful to know how different schema constructs are generated in PHP level so you can have a good idea when you are using them. This post describes How inheritance is used in XML Schema and how it is mapped to PHP code from wsdl2php tool in WSF/PHP.
There are several ways that one schema type can inherit another type. Here are some names use to refer them.
- SimpleType Restriction – Forming simple type by restricting another simple type
- SimpleContent Extension – Forming complex type by extending a simple type
- ComplexContent Extension – Forming complex type by extending another complex type
Note that here the word ‘type’ always refers to a schema type.
It is not straight forward to do a one to one map from these schema structures to a PHP or some other language. But wsdl2php tool does that keeping the simplicity and preserving the original meaning. Lets see how it is done for each of the above mentioned methods of inheriting.
SimpleType Restriction
You can create a simple type by restricting some values of another simple type. Here is an example.
<!-- derivedType from applying simple type restriction for xs:string --> <xs:simpleType name="derivedType"> <xs:restriction base="xs:string"> <xs:enumeration value="a"/> <xs:enumeration value="ab"/> <xs:enumeration value="abc"/> <xs:enumeration value="abcd"/> </xs:restriction> </xs:simpleType>
Here the derivedType is a string, but it can only have values “a”, “ab”, “abc” and “abcd”. This restriction have used the “enumeration” (which we call a facet) to restrict the possible values. You can use other facets like length, minLength, MaxLength and so on. Here are the complete list of facets in the schema specification.
So lets see hows this is mapped to a PHP code. Here we assume this type is used in an schema element called ‘input’.
/** * @var string * NOTE: $input should follow the following restrictions * You can have one of the following value * a * ab * abc * abcd */ public $input;
Note that here it does not say anything about the ‘derivedType’. Rather it says it is of type “String” which is a PHP type and in addition it has some restrictions, or rules when assigning values.
Although it could have been possible to use getters and setters to impose these rules, this uses just a comment about the rules because this way it is really easy the use the variable.
Say we have another type (say derievedType2) restricting the ‘derievedType’, that type will have the combination of restrictions of both types.
Here is the xml schema representation of the ‘derievedType2’.
<!-- derivedType2--> <xs:simpleType name="derivedType2"> <xs:restriction base="tns:derivedType"> <xs:maxLength value="3"/> <xs:minLength value="2"/> </xs:restriction> </xs:simpleType>
And if input2 have that type, the php code will look like this, (Note that it has the combination of rules).
/** * @var string * NOTE: $input2 should follow the following restrictions * You can have one of the following value * a * ab * abc * abcd * Your length of the value should be * Greater than 2 * Less than 3 */ public $input2;
I have highlighted the additional rules compared with $input, so you can see the difference.
SimpleContent Extension
Simple Content extension is extending a simple type to make a complex type. Say we have an element (say with the name “mystring”) and it has “xs:string” simple type.
<xs:element name="mystring" type="xs:string"/>
And here is a valid xml with this schema.
<mystring>this can contain only string</mystring>
So if I say I’m going to make a complex type extending this simple type you may think that I’m going to add element in to that. In fact I will create a complex type by adding an attribute.
<mystring myint="3">this can contain only string</mystring>
The schema to this xml will be something like this. (Note that I have assumed there is an schema element named “mystring” with the type “myStringType”)
<xs:complexType name="myStringType"> <xs:simpleContent> <xs:extension base="xs:string"> <xs:attribute name="myint" type="xs:int"/> </xs:extension> </xs:simpleContent> </xs:complexType>
The PHP generated code for this schema is something like this,
class myStringType { /** * @var int */ public $myint; // The "value" represents the element 'myStringType' value.. /** * @var string */ public $value; }
So as you can see it creates a PHP class for that schema type with member variables for each attributes and finally for the value of the parent type. So in order to represent the above mentioned xml, you will use the following PHP code.
$type = new myStringType(); $type->myint = 3; $type->value = "this can contain only string";
Next we will look at the inheritance with complexContent Extension.
ComplexContent Extension
This is to create a complex type by inheriting another complexType.
<!-- the parent type --> <xs:complexType name="parentType"> <xs:sequence> <xs:element name="demo3" type="xs:int"/> <xs:element name="demo4" type="xs:string"/> </xs:sequence> </xs:complexType> <!-- the child type --> <xs:complexType name="childType"> <xs:complexContent> <xs:extension base="tns:parentType"> <xs:sequence> <xs:element name="demo1" type="xs:int"/> <xs:element name="demo2" type="xs:string"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType>
So here the childType will inherit the ‘demo3’ and ‘demo4’ elements from the parent type. We will see how is the PHP generated code looks like.
class parentType { /** * @var int */ public $demo3; /** * @var string */ public $demo4; } class childType extends parentType { /** * @var int */ public $demo1; /** * @var string */ public $demo2; }
It has uses the PHP inheritance to reprensent the schema inheritance. And the nice thing is you can use the childType for the places you have to use the parentType. That is the theoy we learn at the inheritance class of other languages (Java, C++) too.
So say there is another complexType (say “anotherChildType”) inheriting from the type “parentType” and one another complexType (say “nextLevelChildType”) inheriting this time from “childType” (which in fact inheriting from the “parentType” as mentioned above).
So our types tree would be something like this.
--- parentType | +-------- childType | | | +------------- nexLevelChildType | +-------- anotherChildType
And lets say there is a schema element called ‘input3’ with the type parentType. Then the generated variable for the input3 element will be like following code segment.
/** * @var (object)parentType * Or one of following derived class(es) * childType * nextLevelChildType * anotherChildType */ public $input3;
This comment tells you that you can actually use the inherited types in place of the parent type according to your preferences.
Neat explanation !
Pingback: XML Schema Simple Types & How WSDL2PHP Convert Them To PHP | Dimuthu's Blog