Меню

Php soapclient обработка ошибок

UPDATE July 2018

If you don’t care about getting the SoapFault details and just want to catch any errors coming from the SoapClient you can catch «Throwable» in PHP 7+. The original problem was that SoapClient can «Fatal Error» before it throws a SoapFault so by catching both errors and exceptions with Throwable you will have very simple error handling e.g.

try{
    soap connection...
}catch(Throwable $e){
    echo 'sorry... our service is down';
}

If you need to catch the SoapFault specifically, try the original answer which should allow you to suppress the fatal error that prevents the SoapFault being thrown

Original answer relevant for older PHP versions

SOAP can fatal error calling the native php functions internally which prevents the SoapFaults being thrown so we need to log and suppress those native errors.

First you need to turn on exceptions handling:

try {
    $client = new SoapClient("http://192.168.0.142:8080/services/Logon?wsdl",array(
       'exceptions' => true,
    ));
} catch ( SoapFault $e ) { // Do NOT try and catch "Exception" here
    echo 'sorry... our service is down';
}

AND THEN you also need to silently suppress any «PHP errors» that originate from SOAP using a custom error handler:

set_error_handler('handlePhpErrors');
function handlePhpErrors($errno, $errmsg, $filename, $linenum, $vars) {
    if (stristr($errmsg, "SoapClient::SoapClient")) {
         error_log($errmsg); // silently log error
         return; // skip error handling
    }
}

You will then find it now instead trips a SoapFault exception with the correct message «Soap error: SOAP-ERROR: Parsing WSDL: Couldn’t load from ‘…'» and so you end up back in your catch statement able to handle the error more effectively.

The SoapClient class

(PHP 5, PHP 7, PHP 8)

Introduction

The SoapClient class provides a client for » SOAP 1.1,
» SOAP 1.2 servers.
It can be used in WSDL or non-WSDL mode.

Class synopsis


class SoapClient

{

private
?string
$uri = null;

private
?int
$style = null;

private
?int
$use = null;

private
bool
$trace = false;

private
?resource
$sdl = null;

private
?resource
$typemap = null;

private
?resource
$httpurl = null;

private
?string
$_login = null;

public __construct(?string $wsdl, array $options = [])

public __call(string $name, array $args): mixed

public __doRequest(
    string $request,
    string $location,
    string $action,
    int $version,
    bool $oneWay = false
): ?string

public __setCookie(string $name, ?string $value = null): void

public __setLocation(?string $location = null): ?string

public __soapCall(
    string $name,
    array $args,
    ?array $options = null,
    SoapHeader|array|null $inputHeaders = null,
    array &$outputHeaders = null
): mixed

}

Properties

__last_request
__last_response
__soap_fault
_classmap
_connection_timeout
_cookies
_digest
_encoding
_exceptions
_features
_keep_alive
_login
_password
_proxy_host
_proxy_login
_proxy_password
_proxy_port
_soap_version
_ssl_method
_stream_context
_use_digest
_use_proxy
_user_agent
compression
httpsocket
httpurl
location
sdl
style
trace
typemap
uri
use

Table of Contents

  • SoapClient::__call — Calls a SOAP function (deprecated)
  • SoapClient::__construct — SoapClient constructor
  • SoapClient::__doRequest — Performs a SOAP request
  • SoapClient::__getCookies — Get list of cookies
  • SoapClient::__getFunctions — Returns list of available SOAP functions
  • SoapClient::__getLastRequest — Returns last SOAP request
  • SoapClient::__getLastRequestHeaders — Returns the SOAP headers from the last request
  • SoapClient::__getLastResponse — Returns last SOAP response
  • SoapClient::__getLastResponseHeaders — Returns the SOAP headers from the last response
  • SoapClient::__getTypes — Returns a list of SOAP types
  • SoapClient::__setCookie — Defines a cookie for SOAP requests
  • SoapClient::__setLocation — Sets the location of the Web service to use
  • SoapClient::__setSoapHeaders — Sets SOAP headers for subsequent calls
  • SoapClient::__soapCall — Calls a SOAP function

hugues at zonereseau dot com

11 years ago


When you need to connect to services requiring to send extra header use this method.

Here how we can to it with PHP and SoapClient

<?php

class exampleChannelAdvisorAuth

{

    public
$DeveloperKey;

    public
$Password;

    public function

__construct($key, $pass)

    {

       
$this->DeveloperKey = $key;

       
$this->Password = $pass;

    }

}
$devKey        = "";

$password    = "";

$accountId    = "";
// Create the SoapClient instance

$url         = "";

$client     = new SoapClient($url, array("trace" => 1, "exception" => 0));
// Create the header

$auth         = new ChannelAdvisorAuth($devKey, $password);

$header     = new SoapHeader("http://www.example.com/webservices/", "APICredentials", $auth, false);
// Call wsdl function

$result = $client->__soapCall("DeleteMarketplaceAd", array(

   
"DeleteMarketplaceAd" => array(

       
"accountID"        => $accountId,

       
"marketplaceAdID"    => "9938745"        // The ads ID

   
)

),
NULL, $header);
// Echo the result

echo "<pre>".print_r($result, true)."</pre>";

if(
$result->DeleteMarketplaceAdResult->Status == "Success")

{

    echo
"Item deleted!";

}

?>


info at nospam x valiton x com

7 years ago


CAUTION:
I had quite a bit of trouble trying to make a request with fopen through a proxy to a secure url.  I kept getting a 400 Bad Request back from the remote host.  It was receiving the proxy url as the SNI host.  In order to get around this I had to explicity set the SNI host to the domain I was trying to reach.  It's apparently the issue outlined in this bug:

https://bugs.php.net/bug.php?id=63519

<?php
$domain
= parse_url($file, PHP_URL_HOST);
$proxy_string = "tcp://" . WP_PROXY_HOST  . ":" . WP_PROXY_PORT;
$opts = array(
   
'http' => array( 'proxy' => $proxy_string ),
   
'ssl' => array( 'SNI_enabled' => true, 'SNI_server_name' => $domain));
$context = stream_context_create($opts);
$handle = fopen( $file, 'r', false, $context );
?>

src:
http://php.net/manual/en/context.http.php#114314


Ricardo Pedrassani

6 years ago


If the XML have identities with same name in different levels there is a solution. You don´t have to ever submit a raw XML (this PHP SOAP object don´t allows send a RAW XML), so you have to always translate your XML to a array, like the example below:

$originalXML = "
<xml>
  <firstClient>
      <name>someone</name>
      <adress>R. 1001</adress>
  </firstClient>
  <secondClient>
      <name>another one</name>
      <adress></adress>
  </secondClient>
</xml>"

//Translate the XML above in a array, like PHP SOAP function requires
$myParams = array('firstClient' => array('name' => 'someone',
                                  'adress' => 'R. 1001'),
            'secondClient' => array('name' => 'another one',
                                  'adress' => ''));

$webService = new SoapClient($someURL);
$result = $webService->someWebServiceFunction($myParams);


peter dot hansen at fastit dot net

13 years ago


When you get errors like:
"Fatal error: Uncaught SoapFault exception: [HTTP] Error Fetching http headers in"
after a few (time intensive) SOAP-Calls, check your webserver-config.

Sometimes the webservers "KeepAlive"-Setting tends to result in this error. For SOAP-Environments I recommend you to disable KeepAlive.

Hint: It might be tricky to create a dedicated vhost for your SOAP-Gateways and disable keepalive just for this vhost because for normal webpages Keepalive is a nice speed-boost.


acopantepuy at gmail dot com

7 years ago


when they want to pass variables into the http header that is how it is done:

<?php

$aHTTP

['http']['header'] =  "User-Agent: PHP-SOAP/5.5.11rn";$aHTTP['http']['header'].= "username: XXXXXXXXXXXrn"."password: XXXXXrn";$context = stream_context_create($aHTTP);$client=new SoapClient("https://ocppws-cert.extra.bcv.org.ve:443/AltoValor/BancoUniversal?WSDL",array('trace' => 1,"stream_context" => $context));$result = $client->jornadaActiva();
var_dump($result);
?>


romuloum at hotmail dot com

7 years ago


After migrating to PHP 5.6.5, the soap 1.2 did not work anymore. So I solved the problem by adding optional parameters SSL.
My error: failed to load external entity
How to solve:
        // options for ssl in php 5.6.5
        $opts = array(
            'ssl' => array('ciphers'=>'RC4-SHA', 'verify_peer'=>false, 'verify_peer_name'=>false)
        );
        // SOAP 1.2 client
        $params = array ('encoding' => 'UTF-8', 'verifypeer' => false, 'verifyhost' => false, 'soap_version' => SOAP_1_2, 'trace' => 1, 'exceptions' => 1, "connection_timeout" => 180, 'stream_context' => stream_context_create($opts) );
        $oSoapClient = new SoapClient ( $url . "?WSDL", $params );

David

5 years ago


Under IIS and PHP 7, when creating an new SoapClient, it will through an internal 500 error.

This could be caused by invalid permissions to the wsdl cache directory when using 'cache_wsdl'=>WSDL_CACHE_DISK or WSDL_CACHE_BOTH.

This worked for me:
    try {
        $arrContextOptions=array("ssl"=>array( "verify_peer"=>false, "verify_peer_name"=>false,'crypto_method' => STREAM_CRYPTO_METHOD_TLS_CLIENT));

                $options = array(
                'soap_version'=>SOAP_1_2,
                'exceptions'=>true,
                'trace'=>1,
                'cache_wsdl'=>WSDL_CACHE_NONE,
                'stream_context' => stream_context_create($arrContextOptions)
        );
        $client = new SoapClient('https://url/dir/file.wsdl', $options);

        } catch (Exception $e) {
        echo "<h2>Exception Error!</h2>";
        echo $e->getMessage();
    }


spam at kacke dot de

4 months ago


In case a soap response returns nodes with the attribute xsi:nil="false", they are currently not processed by php-soapclient.

This seems to be a bug (not correct).

Workaround:

class mySoapClient extends SoapClient {
        public function __doRequest($request, $location, $action, $version, $one_way = 0) {
        $response = parent::__doRequest($request, $location, $action, $version, $one_way);
        $response = str_replace('xsi:nil="false"',"",$response);
        return $response;
    }   
}

Took me a day. Hope it can help
Toppi


Guillermo Prandi

10 years ago


To make an HTTPS call with a client certificate, you can do it this way:

1) Create a file containing both the key and the signed certificate. I did this by concatenating my (.pem) key and the certificate I've got signed from my CA (also .pem format). The file looked like this:

-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKagQC1N27Ilb9pWil2NaX2qM8FquXBXK5T1AydOv7sCotsc8MAwbi7
......(snip)......
wAiOCD4K9TyMS76pIS8UyfJl/oIrn7EF24BUpaUfsh8=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIC/zCCAmigAwIBAgIEAIl1JzANBgkqhkiG9w0BAQQuADBQMQswCQYxVQQGEaJV
......(snip)......
eSPds1hLKYSg0bd3uI7LhaDLOC1PPgb77sYe/uYkUWuHBzllts5x/pfue0zaIBKG
Omjy
-----END CERTIFICATE-----

2) Reference your certificate in the creation of the SOAP client, like this:

$protected_url = "https://my-server/?wsdl";
$my_cert_file = "/my/path/to/mycert.pem";

$client = new SoapClient($protected_url, array('local_cert', $my_cert_file) );


fourat dot zouari at tritux dot com

13 years ago


In addition to the KeepAlive trick which is a "server-side" modification, on the "client side" default_socket_timeout should be increased from its default value (60) when you deal with ~slow SOAP servers.
As for the KeepAlive, if creating a new separate vhost for the soap api is not possible, you can add this to your existing vhost: BrowserMatch "^PHP-SOAP" nokeepalive
where PHP-SOAP is the agent name of your soap client, if you dont know what agent name your client use, just checkout the access.log of your apache.

martin dot schenck at plugsurfing dot com

8 years ago


If you want to connect to a server that only supports SSLv2/3 and/or TLS 1.0 (no TLS 2 or 3), tell the SOAP client if you get a connection error by setting the appropriate stream context:
<?php
  $opts
= array(
   
'ssl' => array('ciphers'=>'RC4-SHA')
  );
$objSoapClient = new SoapClient(
   
'https://example.com/?wsdl',
    array (
"encoding"=>"ISO-8859-1",
   
'stream_context' => stream_context_create($opts)
   
// your options
   
);
?>

You might need to disable the SOAP caching of WSDLs in order for the SOAP client to use the new context.

egiardina at badatmath dot com

11 years ago


This one drove me nuts... if you are connecting to a web service run on Cassini, (Visual Studio's web server) from php, you may not be able to call web service functions or load a WSDL out-of-the-box.

My set up is that I am using xampp on my windows development machine, and also using Visual Studio's built in web-server. I built a web service in visual studio. I wrote a simple PHP script, running under xampp, to access this service, so the two projects can 'talk' to each other. What I found was the WSDL was never loaded.

So I moved the WSDL local to the PHP file and accessed it directly. Still no calls. Turns out, PHP's SoapClient seems to have a problem with 'localhost' as a web service endpoint. So I hand-edited the web service endpoint URL to read 127.0.0.1 instead of localhost, and Voila! Web Service calls work:

Here is my PHP, now working:
<?php
$client
= new SoapClient("http://localhost/code/soap.wsdl");
$something $client->HelloWorld(array());
echo
$something->HelloWorldResult;
die();
?>

Here is my modified WSDL:
  <wsdl:service name="MyService">
    <wsdl:port name="MyServiceSoap" binding="tns:MyServiceSoap">
      <soap:address location="http://127.0.0.1:55274/MyService/MyService.asmx" />
....

    </wsdl:port>


mcinantyspam at fejm dot pl

6 years ago


Please note, that if you provide values that contain illegal xml characters (ASCII codes 0-8,  11-12, 14-15 - or x0-x8, xB-xC, xE-xF in hex), php's SoapClient will do send them in request, although such request is improper because it does not meet XML 1.0 requirements.
You always have to replace or remove these characters in your data before supplying them to SoapClient

acopantepuy at gmail dot com

7 years ago


when they want to pass variables into the http header that is how it is done:

<?php

$aHTTP

['http']['header'] =  "User-Agent: PHP-SOAP/5.5.11rn";$aHTTP['http']['header'].= "username: C1040001760102rn"."password: bcv2020rn";$context = stream_context_create($aHTTP);$client=new SoapClient("https://ocppws-cert.extra.bcv.org.ve:443/AltoValor/BancoUniversal?WSDL",array('trace' => 1,"stream_context" => $context));$result = $client->jornadaActiva();
var_dump($result);
?>


Anonymous

9 years ago


I got the following error when trying to load the WSDL file:

Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: <message> 'MessageName' already defined

In my case there was no double definitions but it was including other files - I think one of them contained a duplicate message with a different namespace (which SoapClient doesn't like).

I resolved it by loading the WSDL in SoapUI, right-clicking and selecting "Export definition". The WSDL that then got created worked fine. Hope this helps somebody.


stepan dot zarubin at gmail dot com

11 years ago


Well, this example works fine:

<?php

try { 

   
$x = @new SoapClient("non-existent.wsdl"); 

} catch (
Exception $e) { 

    echo
$e->getMessage();

}

?>



Just make sure use NEW with @.


sheikh303 at gmail dot com

6 years ago


What is the core method to call remote WSDL file while creating SoapClient object?
is it CURL, wget or anyother?

  • #1

Как обработать ошибку при обращении к SOAP?

В PHP при обращении к wsdl если происходит исключение, например неверно указан пароль, то возникает фатальная ошибка Fatal error: SOAP-ERROR: Parsing WSDL.
Как обработать эту ошибку в PHP? Следующий код не позволяет её обработать:

PHP:

 try {
$wsdl = new SoapClient('http://127.0.0.1/ws/moiservis.wsdl',
array('login' => 'user',
'password' => 'parol'));
$dostupna = true;
}catch(Exception $e) {
$dostupna = false;
trigger_error('Ошибка авторизации или внутренняя ошибка сервера. Не удалось связаться с базой.', E_ERROR);
}

  • #2

http://ru2.php.net/manual/en/soapclient.soapclient.php

  • #3

Не помогает. Написал так:

PHP:

 $wsdl = new SoapClient('http://127.0.0.1/ws/moiservis.wsdl',
array('login' => 'user',
'password' => 'parol',
'exceptions'     => false));

Исключение не вызывается.
Предполагаю что причина в том что опция exceptions позволяет обрабатывать исключения при выполнении методов web сервиса, а у меня стоит цель обработать исключение в момент создания объекта. $wsdl = new SoapClient(….). А тут значение опции exceptions не влияет на результат.

Пробовал написать так

PHP:

 $result = new SoapClient('http://127.0.0.1/ws/moiservis.wsdl',
                               array('login'          => 'user',
                                     'password'       => 'parol',
                                     'exceptions'     => 0,
                              ));
if (is_soap_fault($result)) {
      trigger_error("ОШИБКА SOAP Fault: (faultcode: {$result->faultcode}, faultstring: {$result->faultstring})", E_USER_ERROR);
} else{
    print('Настало счастье.');
    return $result;
}

Тоже не работает

DiMA


  • #4

soap в пхп не работает, напиши руками (парсить — через XMLsimple)

если сервис http://127.0.0.1/ws/moiservis.wsdl от мелкософта, зайди туда бразером, тебе напишут текст запроса

  • #5

Автор оригинала: DiMA
soap в пхп не работает, напиши руками (парсить — через XMLsimple)
если сервис http://127.0.0.1/ws/moiservis.wsdl от мелкософта, зайди туда бразером, тебе напишут текст запроса

soap в пхп работает хорошо. Вот только с установкой соединения беда.

Если не найду решения, то вызов соединения напишу из ajax’а. В этом случае ошибка php выразится в том что яваскрипт получит кривой ответ. Вот тут-то я его и обработаю. Но это на крайний случай.

  • #6

попробуй так
‘trace’ => 1
‘exceptions’ => 1

  • #8

Помогло!!! Спасибо.
Теперь позволяет нормально обработать ошибку и не роняет весь сайт.

Gcom

82 / 82 / 18

Регистрация: 03.02.2016

Сообщений: 564

Записей в блоге: 1

1

24.03.2016, 14:17. Показов 3444. Ответов 4

Метки php, soap, массив, функция (Все метки)


Есть функция:

PHP
1
2
3
4
5
6
7
function getQuerySoap ($aArray, $sURL) {
    $sResult = array();
    $sClient = new SoapClient ($sURL);
    $sResult = $sClient -> GetSearch ($aArray);     
 
    return $sResult;
}

Она рабочая, но иногда при работе возникает Fatal error, не так часто (не было возможности сохранить что именно выводит), вопрос в другом, как сделать что бы в случае возникновения ошибки функция возвращала пустой массив.

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Kerry_Jr

Эксперт PHP

3101 / 2586 / 1219

Регистрация: 14.05.2014

Сообщений: 7,231

Записей в блоге: 1

24.03.2016, 14:48

2

Gcom,

Цитата
Сообщение от Gcom
Посмотреть сообщение

PHP
1
2
3
4
5
6
7
function getQuerySoap ($aArray, $sURL) {
    $sResult = array();
    $sClient = new SoapClient ($sURL);
    $sResult = $sClient -> GetSearch ($aArray);     
 
    return $sResult;
}

Попробуйте так

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function getQuerySoap ($aArray, $sURL) {
    $sResult = array();
    try
    {
        $sClient = new SoapClient ($sURL);
        $sResult = $sClient -> GetSearch ($aArray);
    }
    catch (Exception e)
    {
        // если нужно - обработайте исключение
        // если нет - оставьте эту часть пустой
    }   
 
    return $sResult;
}



1



82 / 82 / 18

Регистрация: 03.02.2016

Сообщений: 564

Записей в блоге: 1

24.03.2016, 16:17

 [ТС]

3

Цитата
Сообщение от Kerry_Jr
Посмотреть сообщение

Попробуйте так

Попробую, СПС, а если сработает исключение, выполнение скрипта не остановиться, Fatal error опять не выпадет?



0



Kerry_Jr

Эксперт PHP

3101 / 2586 / 1219

Регистрация: 14.05.2014

Сообщений: 7,231

Записей в блоге: 1

24.03.2016, 16:35

4

Цитата
Сообщение от Gcom
Посмотреть сообщение

если сработает исключение, выполнение скрипта не остановиться, Fatal error опять не выпадет?

Если Fatal error появляется из-за необработанного исключения (что, скорее всего, так и есть), то управление перейдет сначала в блок catch, и если в этом блоке не будет return’а, то после catch’а управление перейдет на следующую за этим блоком операцию, т.е. к

PHP
1
return $sResult;



0



Gcom

82 / 82 / 18

Регистрация: 03.02.2016

Сообщений: 564

Записей в блоге: 1

24.03.2016, 16:57

 [ТС]

5

Цитата
Сообщение от Kerry_Jr
Посмотреть сообщение

Если Fatal error появляется из-за необработанного исключения (что, скорее всего, так и есть), то управление перейдет сначала в блок catch, и если в этом блоке не будет return’а, то после catch’а управление перейдет на следующую за этим блоком операцию

Я почему то же об этом подумал… ладно завтра опробую это:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function getQuerySoap ($aArray, $sURL) {
    $sResult = array();
    try
    {
        $sClient = new SoapClient ($sURL);
        $sResult = $sClient -> GetSearch ($aArray);
    }
    catch (Exception e)
    {
        return $sResult;
    }   
 
    return $sResult;
}



0



ОБНОВЛЕНИЕ июль 2018

Если вы не хотите получать информацию о SoapFault и просто хотите отловить любые ошибки, исходящие от SoapClient, вы можете отловить «Throwable» в PHP 7+. Первоначальная проблема заключалась в том, что SoapClient может «фатальная ошибка» до того, как выдаст SoapFault, поэтому, перехватывая как ошибки, так и исключения с помощью Throwable, вы будете иметь очень простую обработку ошибок, например

try{
    soap connection...
}catch(Throwable $e){
    echo 'sorry... our service is down';
}

Если вам нужно конкретно поймать SoapFault, попробуйте исходный ответ, который должен позволить вам подавить фатальную ошибку, которая предотвращает выброс SoapFault.

Оригинальный ответ, актуальный для более старых версий PHP

SOAP может вызвать фатальную ошибку при вызове собственных функций php внутри, что предотвращает создание SoapFaults, поэтому нам необходимо регистрировать и подавлять эти собственные ошибки.

Сначала нужно включить обработку исключений:

try {
    $client = new SoapClient("http://192.168.0.142:8080/services/Logon?wsdl",array(
       'exceptions' => true,
    ));
} catch ( SoapFault $e ) { // Do NOT try and catch "Exception" here
    echo 'sorry... our service is down';
}

И ТОГДА вам также нужно молча подавить любые «ошибки PHP», исходящие из SOAP, с помощью специального обработчика ошибок:

set_error_handler('handlePhpErrors');
function handlePhpErrors($errno, $errmsg, $filename, $linenum, $vars) {
    if (stristr($errmsg, "SoapClient::SoapClient")) {
         error_log($errmsg); // silently log error
         return; // skip error handling
    }
}

Затем вы обнаружите, что теперь он вместо этого отключает исключение SoapFault с правильным сообщением «Ошибка мыла: SOAP-ERROR: Анализ WSDL: не удалось загрузить из ‘…’», и поэтому вы вернетесь в свой оператор catch, способный обрабатывать ошибка более эффективно.

5 ответов

Fatal error: SOAP-ERROR: Parsing WSDL Значит, WSDL ошибочен и, возможно, отсутствует? поэтому он не относится к мылу. И вы не можете справиться с FATAL ERROR с помощью try catch. См. Эту ссылку: http://ru2.php.net/set_error_handler#35622

Что вы получаете, когда пытаетесь получить доступ к http://192.168.0.142:8080/services/Logon?wsdl в своем браузере?

Вы можете проверить, присутствует ли WSDL, как этот

$handle = curl_init($url);
curl_setopt($handle,  CURLOPT_RETURNTRANSFER, TRUE);

$response = curl_exec($handle);
$httpCode = curl_getinfo($handle, CURLINFO_HTTP_CODE);
if($httpCode == 404) {
    /* You don't have a WSDL Service is down. exit the function */
}

curl_close($handle);

/* Do your stuff with SOAP here. */

yokoloko
05 авг. 2011, в 07:36

Поделиться

Хотя включение исключений, упомянутых в вышеприведенном комментарии, является хорошим шагом для обработки ошибок синтаксического анализа, его недостаточно, поскольку SOAP может привести к фатальной ошибке с использованием собственных функций php.

Итак, сначала вам нужно включить обработку исключений:

try {
    $client = new SoapClient("http://192.168.0.142:8080/services/Logon?wsdl",array(
       'exceptions' => true,
    ));
} catch ( SoapFault $e ) { // Do NOT try and catch "Exception" here
    echo 'sorry... our service is down';
}

И затем вам также необходимо тихо подавлять любые «ошибки PHP», которые происходят из SOAP с помощью специального обработчика ошибок:

set_error_handler('handlePhpErrors');
function handlePhpErrors($errno, $errmsg, $filename, $linenum, $vars) {
    if (stristr($errmsg, "SoapClient::SoapClient")) {
         error_log($errmsg); // silently log error
         return; // skip error handling
    }
}

Затем вы обнаружите, что вместо этого вы отправите исключение SoapFault с правильным сообщением «Ошибка Soap: SOAP-ERROR: Разбор WSDL: не удалось загрузить из»…», и поэтому вы вернетесь в свой оператор catch способный более эффективно обрабатывать ошибку.

MeatPopsicle
06 май 2013, в 08:49

Поделиться

К сожалению, SOAP вызывает фатальную ошибку, когда служба недоступна/недоступна, а не возвращает объект SoapFault.

При этом вы можете настроить его для исключения исключений. Вероятно, вы опустили ту часть, где вы устанавливаете опцию soap_client исключений на false

$client = new SoapClient("http://192.168.0.142:8080/services/Logon?wsdl",array(
    'exceptions' => false,    // change to true so it will throw an exception
));

Устранить исключение, когда служба недоступна:

try {
  $client = new SoapClient("http://192.168.0.142:8080/services/Logon?wsdl",array(
    'exceptions' => true,
  ));
}
catch ( Exception $e )
{
    echo 'sorry... our service is down';
}

Brad Kent
28 янв. 2013, в 18:02

Поделиться

Возможно, лучшая альтернатива:

set_error_handler('my_error_handler');
set_exception_handler('my_exception_handler');

function my_exception_handler($e) {
    exit('Error, something went terribly wrong: '.$e);
}

function my_error_handler($no,$str,$file,$line) {
    $e = new ErrorException($str,$no,0,$file,$line);
    my_exception_handler($e);
}

Где вы можете настроить сообщения об ошибках в указанных функциях.
Я использую его для возврата сообщения в той же ситуации, что и вы, поскольку это может произойти в любое время.

Скажите, что вы отправили сообщение о мыле после первоначального входа в систему, и этот ответ никогда не приходит или не приходит только частично, таким образом вы можете вернуть сообщение без каких-либо script путей, имен и прошивок.
В таких случаях я вообще не возвращаю $e, вместо этого я просто выводил что-то вроде: «Что-то пошло не так, попробуйте еще раз (позже)».

Jonathan
24 сен. 2012, в 14:26

Поделиться

SoapFault не расширяет Exception, улавливает работу определенного типа:

try {
  $client = new SoapClient("http://192.168.0.142:8080/services/Logon?wsdl",array(
    'exceptions' => true,
  ));
}
catch ( SoapFault $e )
{
    echo 'sorry... our service is down';
}

Silvio Pereira Guedes
03 апр. 2013, в 12:06

Поделиться

Ещё вопросы

  • 0Bubble и выбор сортировки c ++
  • 0Ошибки компиляции в atlwin.h
  • 0Регулярное выражение ng-pattern разрешает все символы, кроме десятичного значения
  • 0C ++: Биллинговая программа Mock Catering Company — Не удается вывести неверные данные в файл ошибок
  • 1RadioButtonList Выбор конкретного индекса
  • 1Angular 2 Service: вернуть локальную переменную или дать обещание
  • 0Отображение даты по умолчанию Значение HTML Форма iOS
  • 0Некоторые неправильно понимают в AngularJS
  • 1Почему бы в Zebra QLn220 media.sense_mode var не было пробела с этим кодом?
  • 0Angular JS: встроенный стиль со связанным значением работает на Mac, а не на Windows
  • 0Плагин jQuery для создания потрясающего прокрутки
  • 1Как мне загрузить переменную ruby через Ajax и Javascript?
  • 1Как выяснить, какая панель обновления была обновлена на стороне клиента
  • 1Как установить верхнюю границу изображения, используя кодирование не XML в Android
  • 0Ошибка несериализации PHP
  • 0Visual C ++ 2010 ошибка. Система не может найти файл, указанный при запуске LibICP
  • 0MySQL DELETE на основе SELECT
  • 0Проблема совместимости браузера: макет не работает в Firefox
  • 0Как использовать операторы WHERE и GROUP BY в сценарии MySQL?
  • 1Добавьте две таблицы данных в один лист Excel в c #
  • 1Цепочка работы только для сокращения в Hadoop
  • 0Программно настроить цвет ячейки
  • 0JQuery в прямом эфире отправить событие не звонить?
  • 1org.hibernate.LazyInitializationException: не удалось инициализировать прокси — нет сеанса. Spring + Hibernate + HSQLDB
  • 0Прочитайте лист данных Excel по листам, используя codeigniter, mysql и phpexcel
  • 0jQuery привязать щелчок к атрибуту данных вместо класса
  • 0Автоматический вход после регистрации в AngularFire
  • 1я хочу выбрать данные, когда дата между дд / мм / гггг и дд / мм / гггг
  • 1Как определить поддержку браузера http2 или нет в среде браузера по javascript?
  • 1Как решить NoClassDefFoundError в сервлете Java?
  • 0угловой тест не выполняет код директивы
  • 1ListView.SelectedItems не изменяется при нажатии TextBox в ItemTemplate
  • 1com.microsoft.sqlserver.jdbc.SQLServerException: сбой входа для пользователя ‘sa’
  • 0Не определяется тип переменной (Автоматические глобальные переменные)
  • 0Измените все элементы TABLE на DIV внутри тега TD только jQuery
  • 1Как заставить проект Android и стандартный проект Java играть хорошо?
  • 1EntityFramework: доступ к закрытому закрытию
  • 0незаконные действия в блокноте ++
  • 0JQuery if заявление, основанное на ширине
  • 0Как связать php и MS SQL в LAMP
  • 0Запрос Среднее JS с формой,
  • 0Эффективность std :: tuple и std :: map
  • 0вставить данные из одной таблицы в другую — не работает — возможная ошибка?
  • 0Добавить класс с блесной, прежде чем двигаться дальше
  • 0делая эти два div рядом друг с другом
  • 1Unity не может разрешить зависимость InterfaceInterceptor
  • 0MySQL Исключить сверх Включить в FIND_IN_SET ()
  • 0Предложение по реализации инструмента чтения файлов

I have some simple SOAP client to get data from WSDL and display it.

<?php 
    //Data, connection, auth
    $dataFromTheForm = $_POST['fieldName']; // request data from the form
    $soapUrl = "https://connecting.website.com/soap.asmx?op=DoSomething"; // asmx URL of WSDL
    $soapUser = "username";  //  username
    $soapPassword = "password; // password

    // xml post structure

    $xml_post_string = '<?xml version="1.0" encoding="utf-8"?>
                        <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
                          <soap:Body>
                            <GetItemPrice xmlns="http://connecting.website.com/WSDL_Service"> // xmlns value to be set to your's WSDL URL
                              <PRICE>'.$dataFromTheForm.'</PRICE> // data from the form, e.g. some ID number
                            </GetItemPrice >
                          </soap:Body>
                        </soap:Envelope>';

        $headers = array(
                    "Content-type: text/xml;charset="utf-8"",
                    "Accept: text/xml",
                    "Cache-Control: no-cache",
                    "Pragma: no-cache",
                    "SOAPAction: http://connecting.website.com/WSDL_Service/GetPrice", // your op URL
                    "Content-length: ".strlen($xml_post_string),
                );

        $url = $soapUrl;

        // PHP cURL  for https connection with auth
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_USERPWD, $soapUser.":".$soapPassword); // username and password - declared at the top of the doc
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $soapUrl); // asmx URL of WSDL - declared at the top of the doc
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        // converting
        $response = curl_exec($ch); 
        curl_close($ch);

        // converting
        $response1 = str_replace("<soap:Body>","",$response);
        $response2 = str_replace("</soap:Body>","",$response1);

        // convertingc to XML
        $parser = simplexml_load_string($response2);        



?>

Everything works fine — when WSDL works fine.

But, when WSDL fails( Runtime Error on the server) my site is throwing hundreds of warnings all at line 152 which is:

$parser = simplexml_load_string($response2);

How to detect that WSDL have returned invalid XML (html error msg) and display simple error msg on this base?

I have some simple SOAP client to get data from WSDL and display it.

<?php 
    //Data, connection, auth
    $dataFromTheForm = $_POST['fieldName']; // request data from the form
    $soapUrl = "https://connecting.website.com/soap.asmx?op=DoSomething"; // asmx URL of WSDL
    $soapUser = "username";  //  username
    $soapPassword = "password; // password

    // xml post structure

    $xml_post_string = '<?xml version="1.0" encoding="utf-8"?>
                        <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
                          <soap:Body>
                            <GetItemPrice xmlns="http://connecting.website.com/WSDL_Service"> // xmlns value to be set to your's WSDL URL
                              <PRICE>'.$dataFromTheForm.'</PRICE> // data from the form, e.g. some ID number
                            </GetItemPrice >
                          </soap:Body>
                        </soap:Envelope>';

        $headers = array(
                    "Content-type: text/xml;charset="utf-8"",
                    "Accept: text/xml",
                    "Cache-Control: no-cache",
                    "Pragma: no-cache",
                    "SOAPAction: http://connecting.website.com/WSDL_Service/GetPrice", // your op URL
                    "Content-length: ".strlen($xml_post_string),
                );

        $url = $soapUrl;

        // PHP cURL  for https connection with auth
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_USERPWD, $soapUser.":".$soapPassword); // username and password - declared at the top of the doc
        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $soapUrl); // asmx URL of WSDL - declared at the top of the doc
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        // converting
        $response = curl_exec($ch); 
        curl_close($ch);

        // converting
        $response1 = str_replace("<soap:Body>","",$response);
        $response2 = str_replace("</soap:Body>","",$response1);

        // convertingc to XML
        $parser = simplexml_load_string($response2);        



?>

Everything works fine — when WSDL works fine.

But, when WSDL fails( Runtime Error on the server) my site is throwing hundreds of warnings all at line 152 which is:

$parser = simplexml_load_string($response2);

How to detect that WSDL have returned invalid XML (html error msg) and display simple error msg on this base?

Синтаксис

  • __getFunctions () // Возвращает массив функций для обслуживания (только для режима WSDL)
  • __getTypes () // Возвращает массив типов для службы (только режим WSDL)
  • __getLastRequest () // Возвращает XML из последнего запроса (требуется опция trace )
  • __getLastRequestHeaders () // Возвращает заголовки последнего запроса (требуется опция trace )
  • __getLastResponse () // Возвращает XML из последнего ответа (требуется опция trace )
  • __getLastResponseHeaders () // Возвращает заголовки последнего ответа (требуется опция trace )

параметры

параметр подробности
$ WSDL URI WSDL или NULL при использовании режима, отличного от WSDL
$ варианты Массив вариантов для SoapClient. Режим Non-WSDL требует установки location и uri , все остальные опции являются необязательными. См. Таблицу ниже для возможных значений.

замечания

Класс SoapClient оснащен __call методом. Это не следует вызывать напрямую. Вместо этого это позволяет:

$soap->requestInfo(['a', 'b', 'c']);

Это вызовет requestInfo SOAP requestInfo .


Таблица возможных значений $options ( массив пар ключ / значение ):

вариант подробности
место нахождения URL-адрес сервера SOAP. Требуется в режиме, отличном от WSDL. Может использоваться в режиме WSDL для переопределения URL-адреса.
URI Целевое пространство имен службы SOAP. Требуется в режиме, отличном от WSDL.
стиль Возможными значениями являются SOAP_RPC или SOAP_DOCUMENT . Действует только в режиме, отличном от WSDL.
использование Возможные значения: SOAP_ENCODED или SOAP_LITERAL . Действует только в режиме, отличном от WSDL.
soap_version Возможные значения: SOAP_1_1 (по умолчанию ) или SOAP_1_2 .
аутентификация Включить проверку подлинности HTTP. Возможные значения: SOAP_AUTHENTICATION_BASIC (по умолчанию ) или SOAP_AUTHENTICATION_DIGEST .
авторизоваться Имя пользователя для проверки подлинности HTTP
пароль Пароль для проверки подлинности HTTP
proxy_host URL прокси-сервера
порт прокси Порт прокси-сервера
proxy_login Имя пользователя для прокси
PROXY_PASSWORD Пароль для прокси
local_cert Путь к сертификату клиента HTTPS (для проверки подлинности)
ключевая фраза Парольная фраза для сертификата клиента HTTPS
компрессия Сжимать запрос / ответ. Значение — это битовая SOAP_COMPRESSION_ACCEPT с SOAP_COMPRESSION_GZIP или SOAP_COMPRESSION_DEFLATE . Например: SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP .
кодирование Внутреннее кодирование символов (TODO: возможные значения)
след Boolean , по умолчанию FALSE . Позволяет отслеживать запросы, поэтому ошибки могут быть возвращены. Включает использование __getLastRequest() , __getLastRequestHeaders() , __getLastResponse() и __getLastResponseHeaders() .
classmap Отображать типы WSDL для классов PHP. Значение должно быть массивом с типами WSDL в виде ключей и имен классов PHP в качестве значений.
исключения Логическое значение. Должны быть исключения SOAP ошибок (типа `SoapFault).
время соединения вышло Таймаут (в секундах) для подключения к службе SOAP.
TypeMap Массив отображения типов. Массив должен быть пар ключ / значение со следующими ключами: type_name , type_ns (URI пространства имен), from_xml (обратный вызов принимает один строковый параметр) и to_xml (обратный вызов принимает один параметр объекта).
cache_wsdl Как (если вообще) должен быть кэширован файл WSDL. Возможные значения: WSDL_CACHE_NONE , WSDL_CACHE_DISK , WSDL_CACHE_MEMORY или WSDL_CACHE_BOTH .
user_agent Строка для использования в заголовке User-Agent .
stream_context Ресурс для контекста.
функции SOAP_SINGLE_ELEMENT_ARRAYS маска SOAP_SINGLE_ELEMENT_ARRAYS , SOAP_USE_XSI_ARRAY_TYPE , SOAP_WAIT_ONE_WAY_CALLS .
keep_alive ( Только версия PHP> = 5.4 ) Булево значение. Отправьте либо Connection: Keep-Alive header ( TRUE ), либо Connection: Close header ( FALSE ).
ssl_method ( Только версия PHP> = 5.5 ) Какую версию SSL / TLS использовать. Возможные значения: SOAP_SSL_METHOD_TLS , SOAP_SSL_METHOD_SSLv2 , SOAP_SSL_METHOD_SSLv3 или SOAP_SSL_METHOD_SSLv23 .

Проблема с 32-битным PHP : в 32-битном PHP числовые строки, превышающие 32 бита, которые автоматически отбрасываются на integer с помощью xs:long , приведут к тому, что он достигнет 32-битного предела, отбросив его до 2147483647 . Чтобы обойти это, __soapCall() строки для плавания, прежде чем передавать их в __soapCall() .

Режим WSDL

Сначала создайте новый объект SoapClient , передав URL-адрес в файл WSDL и, при необходимости, массив параметров.

// Create a new client object using a WSDL URL
$soap = new SoapClient('https://example.com/soap.wsdl', [
    # This array and its values are optional
    'soap_version' => SOAP_1_2,
    'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
    'cache_wsdl' => WSDL_CACHE_BOTH,
    # Helps with debugging
    'trace' => TRUE,
    'exceptions' => TRUE
]);

Затем используйте объект $soap для вызова методов SOAP.

$result = $soap->requestData(['a', 'b', 'c']);

Режим без WSDL

Это похоже на режим WSDL, за исключением того, что мы передаем NULL в качестве файла WSDL и не забудьте указать параметры location и uri .

$soap = new SoapClient(NULL, [
    'location' => 'https://example.com/soap/endpoint',
    'uri' => 'namespace'
]);

Classmaps

При создании SOAP-клиента в PHP вы также можете установить ключ classmap в массиве конфигурации. Эта classmap определяет, какие типы, определенные в WSDL, должны быть сопоставлены фактическим классам, а не по умолчанию StdClass . Причина, по которой вы хотели бы сделать это, — это то, что вы можете получить автоматическое заполнение полей и вызовов методов на этих классах, вместо того, чтобы угадывать, какие поля заданы на обычном StdClass .

class MyAddress {
    public $country;
    public $city;
    public $full_name;
    public $postal_code; // or zip_code
    public $house_number;
}

class MyBook {
    public $name;
    public $author;

    // The classmap also allows us to add useful functions to the objects
    // that are returned from the SOAP operations.
    public function getShortDescription() {
        return "{$this->name}, written by {$this->author}";
    }
}

$soap_client = new SoapClient($link_to_wsdl, [
    // Other parameters
    "classmap" => [
        "Address" => MyAddress::class, // ::class simple returns class as string
        "Book" => MyBook::class,
    ]
]);

После настройки класса карты всякий раз, когда вы выполняете определенную операцию, которая возвращает Address или Book , SoapClient будет создавать экземпляр этого класса, заполнять поля данными и возвращать их из вызова операции.

// Lets assume 'getAddress(1234)' returns an Address by ID in the database
$address = $soap_client->getAddress(1234);

// $address is now of type MyAddress due to the classmap
echo $address->country;

// Lets assume the same for 'getBook(1234)'
$book = $soap_client->getBook(124);

// We can not use other functions defined on the MyBook class
echo $book->getShortDescription();

// Any type defined in the WSDL that is not defined in the classmap
// will become a regular StdClass object
$author = $soap_client->getAuthor(1234);

// No classmap for Author type, $author is regular StdClass.
// We can still access fields, but no auto-completion and no custom functions
// to define for the objects.
echo $author->name;

Иногда мы хотим посмотреть, что отправлено и получено в запросе SOAP. Следующие методы возвратят XML в запросе и ответе:

SoapClient::__getLastRequest()
SoapClient::__getLastRequestHeaders()
SoapClient::__getLastResponse()
SoapClient::__getLastResponseHeaders()

Например, предположим, что у нас есть константа ENVIRONMENT и когда значение этой константы установлено в DEVELOPMENT мы хотим getAddress всю информацию, когда вызов getAddress вызывает ошибку. Одним из решений может быть:

try {
    $address = $soap_client->getAddress(1234);
} catch (SoapFault $e) {
    if (ENVIRONMENT === 'DEVELOPMENT') {
        var_dump(
            $soap_client->__getLastRequestHeaders()
            $soap_client->__getLastRequest(),
            $soap_client->__getLastResponseHeaders(),
            $soap_client->__getLastResponse()
        );
    }
    ...
}

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

А вот еще интересные материалы:

  • Яшка сломя голову остановился исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного исправьте ошибки
  • Ясность цели позволяет целеустремленно добиваться намеченного где ошибка
  • Php mysqli вывод ошибки
  • Php mysql код ошибки