PHP’s SoapClient has a bug (PHP 5.2.10 here, still not fixed apparently) when the SOAP service must be accessed on a different port other than 80. The WSDL file is fetched correctly, but all subsequent requests are made without any port in the Host field. This causes a SoapFault exception when trying to call any of the service’s methods.

So if the WSDL location is:

http://example.com:33080/soap/server/path?WSDL

All requests after fetching the WSDL file will be made to:

http://example.com/soap/server/path

The simplest way i could work around this was to extend SoapClient and intercept the constructor and the __doRequest method to inject the port in the location on each request:

class My_SoapClient extends SoapClient {

    public function __construct($wsdl, $options) {
        $url = parse_url($wsdl);
        if ($url['port']) {
            $this->_port = $url['port'];
        }
        return parent::__construct($wsdl, $options);
    }

    public function __doRequest($request, $location, $action, $version) {
        $parts = parse_url($location);
        if ($this->_port) {
            $parts['port'] = $this->_port;
        }
        $location = $this->buildLocation($parts);

        $return = parent::__doRequest($request, $location, $action, $version);
        return $return;
    }

    public function buildLocation($parts = array()) {
        $location = '';

        if (isset($parts['scheme'])) {
            $location .= $parts['scheme'].'://';
        }
        if (isset($parts['user']) || isset($parts['pass'])) {
            $location .= $parts['user'].':'.$parts['pass'].'@';
        }
        $location .= $parts['host'];
        if (isset($parts['port'])) {
            $location .= ':'.$parts['port'];
        }
        $location .= $parts['path'];
        if (isset($parts['query'])) {
            $location .= '?'.$parts['query'];
        }

        return $location;
    }
}

It works for me, and I would like to know if it doesn’t cover your particular case :)