Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

tjsherrill's avatar

Completely stuck trying to consume a SOAP service

I have spent the last 3 working days on this. My google search history is all purple from clicking on every result. Please throw your two cents in if you think you can help.

I am trying to use: URL with SoapClient.

so I am following the documentation and doing:

$wsdl = 'URL';
$params = array(
            'cache_wsdl' => WSDL_CACHE_NONE,
            'encoding' => 'UTF-8',
            'soap_version' => SOAP_1_1,
            'trace' => 1,
            'exceptions' => 1,
            'connection_timeout' => 180,
);
$client = new SoapClient($wsdl, $params);
$params = array(
    'username' =>  'username',
    'password'  =>  'password',
    'applicationName' => 'testing'
);
    
$result =  $client->__soapCall('GetAuthenticationToken', [$params]);
dd($result);

When I run this, I get back:

SOAP-ERROR: Parsing WSDL: Couldn't load from 'URL' : failed to load external entity "URL"

So I wondered if maybe my issue was that the file isn't a wsdl, so I tried:

   $options = array(
            'uri'=>'http://tempuri.org/IDRTrackWebService/',
            'style'=> SOAP_DOCUMENT,
            'use'=> SOAP_LITERAL,
            'location' => 'URL',
            'cache_wsdl'=>WSDL_CACHE_NONE,
            'connection_timeout'=> 15,
            'trace' => true,
            'encoding'=>'UTF-8',
            'exceptions' => true,
        );

        try {
            $client = new SoapClient(null, $options);
            $response = $client->__soapCall('GetAuthenticationToken', $authParams);
            dd($response);}
        catch(Exception $e) {
            die($e->getMessage());
        }

That results in a host not found error.

A couple of other notes:

  1. It works in the browser fine
  2. it seems to be well structured
  3. I am on OSX, with a Laravel 10 build on Php 8.2
  4. I work from home and don't believe there is any firewall or other server related things blocking
  5. There is no authorization required for this service. Your first call just has to be to get the token.

the challenge is that this works in SoapUI, in Postman, and even in Guzzle. My goal is to use SoapClient because then I can work with the returned object is cleaner to implement with.

Thanks in advance. I appreciate the help.

0 likes
16 replies
LaryAI's avatar
Level 58

It seems like you're having trouble with loading the WSDL and making a SOAP call using PHP's SoapClient. Here are a few steps and tips that might help you resolve the issue:

  1. Check if the WSDL is Accessible: Before using the WSDL in your code, make sure you can access it in your browser or by using tools like curl. If you can't access it, there might be network issues or the service might be down.

  2. Verify the WSDL Structure: Ensure that the WSDL is properly structured and valid. You can use online validators to check the WSDL.

  3. Enable PHP Extensions: Make sure that the php_soap extension is enabled in your PHP configuration (php.ini).

  4. Use try-catch for Exception Handling: Wrap your code in a try-catch block to catch any exceptions thrown by SoapClient and get more detailed error messages.

  5. Check Firewall and Proxy Settings: If you're behind a firewall or using a proxy, you might need to configure your PHP settings or SoapClient to handle this.

  6. Use Stream Context: If there are issues with loading the WSDL due to HTTP headers or other requirements, you can create a stream context and pass it to the SoapClient.

Here's an example of how you might adjust your code to include some of these suggestions:

$wsdl = 'http://shenandoahgrowers.appiantracking.com/tracking/DRTrackWebService.svc?wsdl';

$options = [
    'cache_wsdl' => WSDL_CACHE_NONE,
    'encoding' => 'UTF-8',
    'soap_version' => SOAP_1_1,
    'trace' => 1,
    'exceptions' => 1,
    'connection_timeout' => 180,
    'stream_context' => stream_context_create([
        'http' => [
            'header' => "Authorization: Basic " . base64_encode("username:password")
        ]
    ])
];

try {
    $client = new SoapClient($wsdl, $options);
    $params = [
        'username' => 'username',
        'password' => 'password',
        'applicationName' => 'testing'
    ];

    $result = $client->__soapCall('GetAuthenticationToken', [$params]);
    var_dump($result);
} catch (Exception $e) {
    echo 'Exception: ' . $e->getMessage();
}

In the above code, I've added a stream_context to the options array, which you might need if there are specific HTTP headers required by the SOAP service.

If you continue to have issues, you might want to check the server logs (if you have access) to see if there's more information on why the WSDL can't be loaded. Additionally, you can use $client->__getLastRequest() and $client->__getLastResponse() after a SOAP call to debug the raw request and response.

Remember that the actual issue might be specific to your server configuration, network environment, or the SOAP service itself, so you might need to adjust the solution based on the exact error messages and behavior you observe.

gych's avatar

Did you already try to connect like this?

$result =  $client->GetAuthenticationToken($params);

Or this

$result =  $client->GetAuthenticationToken(['parameters' => $params]);
tjsherrill's avatar

@gych Thanks for the reply. Yes. My first attempt issue is that it can't "load the wsdl". My second is that it can't find the host. My feeling is that if one of those options worked, the auth call would be fine.

Snapey's avatar

I used this which obviously failed, but did not complain about the wsdl and returned XML response.


ini_set('default_socket_timeout', 10);

$options = array(
    'soap_version' => SOAP_1_1,
    'exceptions' => true,
    'trace' => 1,
    'cache_wsdl' => WSDL_CACHE_MEMORY,
    'login' => 'login',
    'password' => 'password',
    'connection_timeout' => 10,
    'style' => SOAP_RPC,
    'use' => SOAP_ENCODED,
);

$url= 'http://shenandoahgrowers.appiantracking.com/tracking/DRTrackWebService.svc?wsdl';

$client = new \SoapClient($url, $options);

$client->GetAuthenticationToken();

output

{#1283
    +"GetAuthenticationTokenResult": {#1282
      +"authenticationField": null,
      +"responseStatusField": {#1281
        +"errorField": {#1280
          +"ResponseStatusError": {#1279
            +"codeField": 100,
            +"messageField": "Unexpected error occurred",
          },
        },
        +"warningField": null,
      },
    },
  }
tjsherrill's avatar

@Snapey Thanks a ton for your response. That is what I would expect. I would be able to use it if that was the result I got.

But I just tested your code, and I got:

SOAP-ERROR: Parsing WSDL: Couldn't load from 'http://shenandoahgrowers.appiantracking.com/tracking/DRTrackWebService.svc?wsdl' : failed to load external entity "http://shenandoahgrowers.appiantracking.com/tracking/DRTrackWebService.svc?wsdl"

I can still hit it in the browser. What can be causing this sort of thing?

Snapey's avatar

@tjsherrill I checked that the wsdl is parsed with $client->__getFunctions()

[
    "GetAuthenticationTokenResponse GetAuthenticationToken(GetAuthenticationToken $parameters)",
    "GetBranchesResponse GetBranches(GetBranches $parameters)",
    "GetFormsResponse GetForms(GetForms $parameters)",
    "GetRouteSummaryByPlannedStartDateResponse GetRouteSummaryByPlannedStartDate(GetRouteSummaryByPlannedStartDate $parameters)",
    "GetRouteDetailByPlannedStartDateResponse GetRouteDetailByPlannedStartDate(GetRouteDetailByPlannedStartDate $parameters)",
    "GetRouteDetailByModifiedDateResponse GetRouteDetailByModifiedDate(GetRouteDetailByModifiedDate $parameters)",
    "GetRouteDetailAndBranchIdByModifiedDateResponse GetRouteDetailAndBranchIdByModifiedDate(GetRouteDetailAndBranchIdByModifiedDate $parameters)",
    "GetRouteDetailByDateRangeResponse GetRouteDetailByDateRange(GetRouteDetailByDateRange $parameters)",
    "GetOrderDetailByDateResponse GetOrderDetailByDate(GetOrderDetailByDate $parameters)",
    "GetOrderDetailByModifiedDateResponse GetOrderDetailByModifiedDate(GetOrderDetailByModifiedDate $parameters)",
    "GetOrderDetailsByModifiedDateAndBranchIdsResponse GetOrderDetailsByModifiedDateAndBranchIds(GetOrderDetailsByModifiedDateAndBranchIds $parameters)",
    "GetUserAndQuantityFieldsResponse GetUserAndQuantityFields(GetUserAndQuantityFields $parameters)",
    "ImportActualsResponse ImportActuals(ImportActuals $parameters)",
    "ImportActualsFromMultipleBranchesResponse ImportActualsFromMultipleBranches(ImportActualsFromMultipleBranches $parameters)",
    "GetAccountDetailsByBranchResponse GetAccountDetailsByBranch(GetAccountDetailsByBranch $parameters)",
    "BuildRouteFromOrderIdsResponse BuildRouteFromOrderIds(BuildRouteFromOrderIds $parameters)",
    "UnloadOrdersResponse UnloadOrders(UnloadOrders $parameters)",
    "AddOrdersResponse AddOrders(AddOrders $parameters)",
    "LockStopsResponse LockStops(LockStops $parameters)",
    "UnlockStopsResponse UnlockStops(UnlockStops $parameters)",
    "GetAccountDetailsByModifiedDateAndBranchResponse GetAccountDetailsByModifiedDateAndBranch(GetAccountDetailsByModifiedDateAndBranch $parameters)",
    "ImportOrdersResponse ImportOrders(ImportOrders $parameters)",
    "ImportExtractFileResponse ImportExtractFile(ImportExtractFile $parameters)",
    "ImportRoutesResponse ImportRoutes(ImportRoutes $parameters)",
    "ImportDriversResponse ImportDrivers(ImportDrivers $parameters)",
    "ImportDevicesResponse ImportDevices(ImportDevices $parameters)",
    "SuggestRoutesResponse SuggestRoutes(SuggestRoutes $parameters)",
    "GetOrderDetailsByOrderIdsResponse GetOrderDetailsByOrderIds(GetOrderDetailsByOrderIds $parameters)",
    "GetOrderDetailsAndEventsByOrderIDsResponse GetOrderDetailsAndEventsByOrderIDs(GetOrderDetailsAndEventsByOrderIDs $parameters)",
    "GetOrderEventsByTypeAndDateResponse GetOrderEventsByTypeAndDate(GetOrderEventsByTypeAndDate $parameters)",
    "ImportAccountsResponse ImportAccounts(ImportAccounts $parameters)",
    "ExportAccountsResponse ExportAccounts(ExportAccounts $parameters)",
    "ChangeAccountFrequencyResponse ChangeAccountFrequency(ChangeAccountFrequency $parameters)",
    "GetMasterRoutesResponse GetMasterRoutes(GetMasterRoutes $parameters)",
    "ImportBranchesResponse ImportBranches(ImportBranches $parameters)",
    "GetTruckProfilesResponse GetTruckProfiles(GetTruckProfiles $parameters)",
    "GetMaxRouteDetailByBranchAndDispatchDateResponse GetMaxRouteDetailByBranchAndDispatchDate(GetMaxRouteDetailByBranchAndDispatchDate $parameters)",
    "ImportAssetsResponse ImportAssets(ImportAssets $parameters)",
    "TransferAssetsResponse TransferAssets(TransferAssets $parameters)",
    "DecommissionAssetsResponse DecommissionAssets(DecommissionAssets $parameters)",
    "ImportCostingRulesResponse ImportCostingRules(ImportCostingRules $parameters)",
    "GetCostingRulesByBranchResponse GetCostingRulesByBranch(GetCostingRulesByBranch $parameters)",
    "UpdateAccountEmailEventsResponse UpdateAccountEmailEvents(UpdateAccountEmailEvents $parameters)",
  ]

So parsing the WSDL seems ok.

The problem appears to be localised to you. Are you on a business network, maybe behind a proxy?

can you curl the wsdl?

tjsherrill's avatar

@Snapey that all looks right. It feels like you might be right. I am on my home internet, not business (USA), on my mac. I am running this project inside Laravel Herd. But I also tested on Mamp (just to see). Is there a way to see if I am behind a proxy or firewall?

Snapey's avatar

@tjsherrill unlikely if its your own kit

I ran the tests in tinkerwell so no web server (and herd) involved

tjsherrill's avatar

@Snapey I just picked up Tinkerwell and tested, and I am getting the same error response (SOAP-ERROR: Parsing WSDL: Couldn't load from). I then tested it again in Postman, and it works there.

So somehow I just can't with php/laravel/tinkerwell.

tjsherrill's avatar

Using tinkerwell I did find a better log:

WARNING SoapClient::__construct(URL): Failed to open stream: Operation timed out in phar:///Applications/Tinkerwell.app/Contents/Resources/tinkerwell/tinker.phar/src/Shell/CustomExecutionLoopClosure.php(38) : eval()'d code on line 21.

WARNING SoapClient::__construct(): I/O warning : failed to load external entity "URL" in phar:///Applications/Tinkerwell.app/Contents/Resources/tinkerwell/tinker.phar/src/Shell/CustomExecutionLoopClosure.php(38) : eval()'d code on line 21.

SoapFault

SOAP-ERROR: Parsing WSDL: Couldn't load from 'URL' : failed to load external entity "URL"

I doubt this helps. but I figured I'd share

tjsherrill's avatar

@Snapey Just did and it works. Which is good on one hand, I'll see about just using curl. I'd love to know why SoapClient didn't work.

tjsherrill's avatar

And just to make it even more frustrating: I deployed this to forge, and the Soapclient call worked. What the @#% $@ is wrong with my machine that its blocking it.

kokoshneta's avatar

I notice the address you’re trying to load is HTTP, not HTTPS. Do you have your application secured on your dev machine? Might it be that it won’t load a non-secure external resource via a secured site? As far as I can see, just by opening the URL in my browser and changing HTTP to HTTPS, the external site works the same with both protocols, so perhaps just try adding the s in the URL and see if that magically does something?

(Then again, the deployed Forge site is, I would hope, secured, so perhaps that’s not it after all…)

phuyer's avatar

Add in $options line:

 'location' => 'http://shenandoahgrowers.appiantracking.com/tracking/DRTrackWebService.svc'

Please or to participate in this conversation.