2

I am trying to write a class that communicate with an API. I would like to override the standard Exception class in PHP to return the message, error code that I want.

I have added this extension

<?php namespace API;

/**
 * API Exception
 *
 * @package ICWS
 */
class ApiException extends \Exception
{
    public function __construct($message, $code = 0)
    {
        // Custom ICWS API Exception Message
        $apiMessage = 'ICWS API Error: ' . $message;

        //More code to come to custom the error message/code.....

        // Run parent construct using custom message
        parent::__construct($apiMessage, $code);
    }
}
?> 

Then when needed I create new ApiException like so

    throw new ApiException($errorMessage, $errorNo);

Finally I wrap the function that throws an exception by try{} catch() block to capture the exception.

However, I still get the a fatal error instead of just the message that I provided.

Here is my code

public function createSession($userID, $password){

    $data = array('userID' => $userID,
                  'password' => $password);

    try {

        $data = $this->_makeCall('POST', 'connection', $data);

        $this->_csrfToken = $data['csrfToken'];
        $this->_sessionId = $data['sessionId'];
        $this->_alternateHostList = $data['alternateHostList'];

    } catch (Exception $e){
        $this->_displayError($e);
    }
}

private function _makeCall($uri, $data = false, $header = array())
{
    $ch = curl_init();
    $url = $this->_baseURL . $uri;

    //disable the use of cached connection
    curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);

    curl_setopt($ch, CURLOPT_URL, $url);

    //return the respond from the API
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    if(!empty($header)){
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    }

    curl_setopt($ch, CURLOPT_POST, true);

    if ($data){
        $JSON = json_encode( $data );
        curl_setopt( $ch, CURLOPT_POSTFIELDS, $JSON );
    }


    $result = curl_exec($ch);

    //throw cURL exception
    if($result === false){
        $errorNo = curl_errno($ch);
        $errorMessage = curl_error($ch);

        throw new ApiException($errorMessage, $errorNo);
    }   

    $result = json_decode($result, true);

    //throw API exception
    if(  $this->_hasAPIError($result) )
    ){          
        throw new ApiException($result['message'], 0);
    }

    return $result;
}

private function _displayError(Exception $e){
    echo 'Error Number: ' . $e->getCode() . "\n";
    echo 'Error Description: ' . $e->getMessage() . "\n\n";     
}

private function _hasAPIError($result){
    if(    isset($result['errorId']) && !empty($result['errorId'])
        && isset($result['errorCode']) && !empty($result['errorCode'])
        && isset($result['message']) && !empty($result['message'])
    ){          
        return true;
    }

    return false;       
}

I would like to see something like this at then end "if there is an error"

Error Number: 0
Error Description: ICWS API Error: The authentication process failed

This is what I currently get

Fatal error: Uncaught exception 'API\ApiException' with message 'ICWS API Error: The authentication process failed.' in C:\phpsites\icws\API\ICWS.php:130 Stack trace: #0 C:\phpsites\icws\API\ICWS.php(57): API\ICWS->_makeCall('connection', Array) #1 C:\phpsites\icws\index.php(17): API\ICWS->createSession('user', 'pass') #2 {main} thrown in C:\phpsites\icws\API\ICWS.php on line 130
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
Jaylen
  • 39,043
  • 40
  • 128
  • 221

2 Answers2

3

You did not import the Exception class into your namespace, so when doing catch (Exception $e), Exception is an unknown class (because PHP is assuming API\Exception) and PHP will not notice that APIException is a subclass of Exception. Curiously, PHP does not complain about catching a non-existing class (I've just confirmed this locally with PHP 5.6.8).

The following should work:

catch (\Exception $e) {
    // ...
}

Alternatively:

use Exception;
// ...
catch (\Exception $e) {
    // ...
}
helmbert
  • 35,797
  • 13
  • 82
  • 95
-1

The error is that you are catching Exception, not ApiException. Try this:

try {
    $data = $this->_makeCall('POST', 'connection', $data);
    $this->_csrfToken = $data['csrfToken'];
    $this->_sessionId = $data['sessionId'];
    $this->_alternateHostList = $data['alternateHostList'];
} catch (ApiException $e){ // Here is the change: Exception to ApiException
    $this->_displayError($e);
}
mathielo
  • 6,725
  • 7
  • 50
  • 63
  • That did it :) I should have known that.. thank you so much :) – Jaylen May 05 '15 at 21:29
  • Yeah @Mike, most of the times it's the small things that passes us by unnoticed. If this did answer to your question, please mark as the correct answer so people can know your question was answered ;) – mathielo May 05 '15 at 21:31
  • 1
    @mathielo, Sorry, but that's just wrong. A catch statement in PHP will also catch sub-classes of the specified exception class (just that the OP tried to catch `API\Exception` instead of `\Exception` (mind the namespace). – helmbert May 05 '15 at 21:32
  • you got it :) I was just waiting to accept due to time restriction – Jaylen May 05 '15 at 21:32
  • You're right @helmbert ! The namespace got me there. – mathielo May 05 '15 at 21:34
  • 1
    @Mike take a look at **helmbert**'s comment and answer. It provides more important and detailed information. – mathielo May 05 '15 at 21:35