1
\$\begingroup\$

I thought this was pretty slick - maybe not, I just wanted to share and maybe get some feedback:

As part of a REST client class:

Accepts the JSON response from REST or REST-like service, searches through to find multiple errors, or return success indicator.

You define success and failure in a small multidimensional array broken down by resource/method, I have it set to count success/failure when it finds the properties with matching names, but could check values too:

private $response_definitions = array(
    'authenticate' => array(
        'success' => array( 'accessHash' ),
        'failure' => array( 'authErrorObj' ),
    ),
    'create_order' => array(
        'success' => array( 'orderSuccessObj' ),
        'failure' => array( 'orderErrorObj', 'deviceErrorObj' ),
    ),
    'cancel_order' => array(
        'success' => array( 'cancelOrderObj' ),
        'failure' => array( 'orderErrorObj' ),
    )                           
);

You hand it your response - already decoded, in this case

$this->checkResponse($action,json_decode($response));

Loops through our response. Fills a "error" property in the main class for errors, and also returns the success object, defined above, if found.

/**
 * checkForErrors
 * Here we will take whatever response we have, and look for errors in it.
 * sending the thrid parameter as 'false' kicks off a recursive search through the provided response()
 * the search looks for both success and failure properties, defined in the class properties.
 * if it finds an error value, it builds up the class' "error" property
 * if it doesn't find a success, the first iteration (with the false third parameter) adds an error as well
 * @param  action string the action we launched so we can know what kind of errors to look for
 * @param  response object the full response object, converted to a php object with json_decode
 * @param  type string when this is false, it will begin the recursion to look for successes and failures
 * @void
 */
function checkResponse( $action, $response, $type=FALSE )
{
    // the first, non-recursive iteration
    if( $type === FALSE ){
        $this->checkResponse( $action, $response, 'failure' );
        $success_result = $this->checkResponse( $action, $response, 'success' );

        if( $success_result === NULL ){
            $this->errors[] = (object)array(
                'name'        => 'TEK-00000',
                'description' => 'Success Property Not Found!'
            );                  
        }
    }else // the recursive iterations
    {
        $definitions = $this->response_definitions[$action][$type];
        foreach( $response as $property => $value ) 
        {       
            // if success and property is in 'success' array, then return the property
            if( $type == 'success' && in_array( $property, $definitions ) ){
                return $property;
            }

            // if failure and property is in 'failure' array, then add the error to the error property      
            if( $type == 'failure' && in_array( $property, $definitions ) ){
                $this->errors[] = (object)array(
                    'name'        => $value->errorCode,
                    'description' => $value->errorMessage
                );              
            }
            // if property is an object or an array, recursively search through it as well
            if ( is_object( $value ) || is_array( $value ) ){
                // if we're looking at successes, be sure to send the result up the recursion chain.
                if    ( $type == 'success' ){ return $this->checkResponse( $action, $value, $type ); }
                elseif( $type == 'failure' ){        $this->checkResponse( $action, $value, $type ); }
            }
        }
    }
}

Anyway, open to improvements I'm sure. I kind of like that you kick it off by setting one flag, then it handles are the recursion within itself and hands any success response up the chain.

\$\endgroup\$
  • \$\begingroup\$ If you're writing your own restful service, why wouldn't you have it define whether it failed or not on its own? E.g. have every response in a format like: {"success":true, "errorMessage":null, "data":"my data"},{"success":false, "errorMessage":"Bad Input", "data":null}. \$\endgroup\$ – MrLore Jan 15 '14 at 23:43
  • 1
    \$\begingroup\$ Ah, I'm not writing my own service, this is just for REST client. \$\endgroup\$ – dgig Jul 16 '14 at 13:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.