When working against complex soap servers from PHP it’s generally a nice thing to be able to act on exceptions and not just provide the error message. I’ve been working against X-Fire web services for the last few months, and every time an exception is thrown it’s returned as a SoapFault with the actual exception name as property in the detail field. I wanted proper exceptions which I could do something useful with, so I poked around and came up with something which fixes this. The basic idea is to catch the soap fault exception, parse it for information and build a new exception based on the name which is retrieved. The code is a bit gritty since the actual name of the exception is a field, but that’s nothing that reflection can’t solve. The doRequest method is the method used to call the web service methods. This is a part of my soap client class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | /** * Do the soap request * */ protected function doRequest($name, $args = array()) { try { $response = $this->__soapCall($name, $args, $this->options); return $response; } catch(Exception $e) { $newEx = $this->buildException($e); throw $newEx; } } /** * parses a soap fault and returns the error code and message * used by buildException * * @param SoapFault $e * @return array */ protected function parseSoapFault(SoapFault $e) { $pos = strpos($e->faultstring, ':'); $code = ""; if($pos) { $code = substr($e->faultstring, 0, $pos); $message = trim(substr($e->faultstring, $pos+1, strlen($e->faultstring))); } else { $message = $e->faultstring; } return array($code, $message); } /** * This method takes a SoapFault and builds a proper exception from it * * The SoapFault can hold a server side exception name in it's detail field. This * method takes a peek to see if that field exists, and if it does the name of the * field is extracted via reflection. A new exception is created of the class that * was just retrieved and the message and code is set. * * The message and error code is extracted from the soap fault. * @param unknown_type $e * @return unknown */ protected function buildException($e){ list($code, $message) = $this->parseSoapFault($e); if (!isset($e->detail)){ // No exception found $ex = new GenericException($message,$code); return $ex; } // get the actual name of the exception $reflectionObject = new ReflectionObject($e->detail); $properties = $reflectionObject->getProperties(); $exceptionName = $properties[0]->name; $exception = new $exceptionName($message,$code); return $exception; } |