Matthew Hodge
Full Stack Developer

I was recently tasked with implementing a SOAP service in order to interact with an accounting system and an ecommerce store, to update products based on the data returned from the service i.e pricing and stock updates scheduled to run on a schedule.

I use a great WsdlToPhp/PackageGenerator on GitHub to generate PHP classes from a WSDL, I thought to myself why not write about it in the hopes of it being of use for other developers.

Lets take a look at this example calculator wsdl which will allow us to use the functions thereof to perform some calculations. I'm sure your WSDL will be more complex and have a better use case, but this is just to get you started

directory structure
- calculator.php
- index.php
- composer.json
sample soap service
http://www.dneonline.com/calculator.asmx?wsdl
composer.json
{
    "name": "mhodge/playground",
    "autoload": {
        "psr-4": {
            "Calculator\\": "Calculator/src/Calculator"
        }
    },
    "require-dev": {
        "wsdltophp/packagegenerator": "^4.1"
    }
}

calculator.php
<?php
require_once 'vendor/autoload.php';

use WsdlToPhp\PackageGenerator\ConfigurationReader\GeneratorOptions;
use WsdlToPhp\PackageGenerator\Generator\Generator;

$options = GeneratorOptions::instance();
$options
    ->setOrigin('http://www.dneonline.com/calculator.asmx?wsdl')
    ->setDestination('./Calculator')
    ->setComposerName('calculator')
    ->setNamespace('Calculator');

    // Generator instantiation
$generator = new Generator($options);

// Package generation
$generator->generatePackage();
index.php
<?php
require_once 'vendor/autoload.php';

$options = [
    WsdlToPhp\PackageBase\AbstractSoapClientBase::WSDL_URL => 'http://www.dneonline.com/calculator.asmx?wsdl',
    WsdlToPhp\PackageBase\AbstractSoapClientBase::WSDL_CLASSMAP => \Calculator\ClassMap::get(),
];
/**
 * Samples for Add ServiceType
 */
$add = new \Calculator\ServiceType\Add($options);
/**
 * Sample call for Add operation/method
 */
if ($add->Add(new \Calculator\StructType\Add(668,669)) !== false) {
    print_r($add->getResult());
    print_r("<br />");
} else {
    print_r($add->getLastError());
    print_r("<br />");
}

Why 668 + 669 ? well thats just 1337!

There are many other options you can set and use for your project other than the ones I used above, I highly recommend going through all of them to get familiar so you can apply to your use case.

One of the options I find really usefull is overriding the xsd_types of the wsdl you are generating this Weather WSDL for example uses multiple XSD types string, decimal, datetime etc. It's sometimes usefull to extend the default xsd_types.yml and specify the type you want returned for your WSDL.

i.e you could update the index.php and set the setXsdTypesPath directive

calculator.php - updated
require_once 'vendor/autoload.php';

use WsdlToPhp\PackageGenerator\ConfigurationReader\GeneratorOptions;
use WsdlToPhp\PackageGenerator\Generator\Generator;

$options = GeneratorOptions::instance();
$options
    ->setOrigin('http://www.dneonline.com/calculator.asmx?wsdl')
    ->setDestination('./Calculator')
    ->setComposerName('calculator')
    ->setNamespace('Calculator')
    ->setXsdTypesPath('xsd_types.yml');

    // Generator instantiation
$generator = new Generator($options);

// Package generation
$generator->generatePackage();
xsd_types.yml
# List of XSD types that can be defined as a type hint parameter.

xsd_types:
    anonymous: "string"
    anySimpleType: "string"
    anyType: "string"
    anyURI: "string"
    base64Binary: "string"
    bool: "bool"
    boolean: "bool"
    byte: "string"
    date: "string"
    dateTime: "string"
    decimal: "float"
    double: "float"
    DayOfWeekType: "string"
    DOMDocument: "string"
    duration: "string"
    ENTITY: "string"
    ENTITIES: "string"
    float: "float"
    gDay: "string"
    gMonth: "string"
    gMonthDay: "int"
    gYear: "string"
    gYearMonth: "int"
    hexBinary: "string"
    int: "int"
    integer: "int"
    ID: "string"
    IDREF: "string"
    IDREFS: "string"
    language: "string"
    long: "int"
    Name: "string"
    negativeInteger: "int"
    nonNegativeInteger: "int"
    nonPositiveInteger: "int"
    normalizedString: "string"
    NCName: "string"
    NMTOKEN: "string"
    NMTOKENS: "string"
    NOTATION: "string"
    positiveInteger: "int"
    QName: "string"
    short: "int"
    string: "string"
    timestamp: "int"
    timeStamp: "int"
    time: "string"
    token: "string"
    unsignedByte: "string"
    unsignedInt: "int"
    unsignedLong: "int"
    unsignedShort: "int"
    UID: "string"
    UNKNOWN: "string"

Lets say you have the following class, how do you output the contents of car variable?

class Car{
    public $make;

    public function __construct($make = null){
        $this->make = $make;
    }
}
$car = new Car('VW');

In order to debug the variable and output it to the screen you can use the following:

print_r($car)

You could also store the output into a variable which could be written later rather than output the contents to screen for example you would write it to a file:

$results = print_r($car, true); // $results now contains output from print_r