SoapClient Timeouts Don’t Work the Way You Think

📖 1 minute read

You’d think adding a timeout to PHP’s SoapClient would be straightforward. Maybe a constructor option like 'timeout' => 30?

Nope. Welcome to PHP SOAP hell.

The only way to set a request timeout on native SoapClient is ini_set():

ini_set('default_socket_timeout', 30);
$client = new SoapClient($wsdl, $options);

The connection_timeout constructor option? That’s only for the initial TCP handshake, not the actual SOAP call. It won’t save you from slow API responses.

But there’s a cleaner approach — extend SoapClient and override __doRequest() to use Guzzle:

class GuzzleSoapClient extends SoapClient
{
    private GuzzleClient $guzzle;

    public function __construct($wsdl, array $options = [])
    {
        parent::__construct($wsdl, $options);
        $this->guzzle = new GuzzleClient([
            'timeout' => $options['timeout'] ?? 30,
        ]);
    }

    public function __doRequest(
        $request, $location, $action, $version, $oneWay = 0
    ): ?string {
        $response = $this->guzzle->post($location, [
            'body' => $request,
            'headers' => ['SOAPAction' => $action],
        ]);
        return (string)$response->getBody();
    }
}

Drop-in replacement. Actual timeout support. No ini_set() hacks.

Daryle De Silva

VP of Technology

11+ years building and scaling web applications. Writing about what I learn in the trenches.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *