Устранение ошибок PHP SOAP
Я получаю отчаяние, все, что мне нужно, - это простая обработка ошибок, когда веб-служба PHP SOAP отключена, чтобы эхо-сообщение об ошибке было зарегистрировано. Пожалуйста, помогите мне!
В настоящий момент все еще отображается ошибка (наряду с предупреждениями):
Fatal error: SOAP-ERROR: Parsing WSDL
Вот script:
<?php
session_start();
$login="0000000000000nhfidsj"; //It is like this for testing, It will be changed to a GET
$username = substr($login,0,13); //as password is always 13 char long
//(the validation is done int he javascript)
$password = substr($login,13);
try
{
ini_set('default_socket_timeout', 5); //So time out is 5 seconds
$client = new SoapClient("http://192.168.0.142:8080/services/Logon?wsdl"); //locally hosted
$array = $client->login(array('username'=>$username,
'password'=>$password));
$result = $array->return;
}catch(SoapFault $client){
$result = "0";
}
if($result == "true")//as this would be what the ws returns if login success
{
$_SESSION['user'] = $login;
echo "00";
}
else
{
echo "01 error: login failed";
}
?>
Ответы
Ответ 1
ОБНОВЛЕНИЕ июль 2018
Если вас не интересует получение сведений о SoapFault и вы просто хотите отследить любые ошибки, возникающие в SoapClient, вы можете перехватить "Throwable" в PHP 7+. Первоначальная проблема заключалась в том, что SoapClient может "Fatal Error" до того, как он генерирует 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 в состоянии обработать ошибку более эффективно.
Ответ 2
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. */
Ответ 3
К сожалению, 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';
}
Ответ 4
Возможно, лучшая альтернатива:
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, вместо этого я просто выводил что-то вроде: "Что-то пошло не так, попробуйте еще раз (позже)".
Ответ 5
Я закончил с этим так:
libxml_use_internal_errors(true);
$sxe = simplexml_load_string(file_get_contents($url));
if (!$sxe) {
return [
'error' => true,
'info' => 'WSDL does not return valid xml',
];
}
libxml_use_internal_errors(false);
Сделайте свой мыльный звонок после этой проверки.
Ответ 6
Все оказалось гораздо более тривиальным - при использовании пространств имен обязательно указывайте root ns! Те, кто catch (SoapFailt $fault)
- неправильно, правильный путь catch (\ SoapFault $fault)
Ответ 7
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';
}