Jump to content

Recommended Posts

Why isn't $e set in the finally block?  You might say it is.  Please read on...

 

try {
    $pdo->beginTransaction();
    //insertSomeRecords();
    //Just used to fake a PDOException
    $pdo->prepare('SELECT x FROM invalid_table');
    return true;
} catch (PDOException $e) {
    //Some logic goes here
    throw true?$e: new Exception;
} finally {
    //Why isn't $e set?
    syslog(LOG_INFO,isset($e)?'$e is set':'$e is not set');
    if (isset($e) || !$pdo->commit()) {
        syslog(LOG_INFO,'rollBack');
        $pdo->rollBack();
    }
}
I happen to be using Slim, and I think Slim is somehow catching the exception and somehow resolving it before getting to the finally block, and thus I inappropriately commit the transaction.  Can I use a finally block when using Slim?  If so, how?
 
On a side note, am I doing error handling correctly as shown below?  Two specific areas I am confused with are whether I should use $c['response']->withJson() or $response->withJson()and how $methods is passed to the handler.
 

Thank you

<?php
$c = new \Slim\Container([]);


$c['errorHandler'] = function($c){
    return function ($request, $response, $e) use ($c){
        syslog(LOG_ERR,'ERROR in '.$e->getFile()." (".$e->getline().'): '.$e->getMessage());
        if ($e instanceof NotFoundException){
            return $c['notFoundHandler']($request, $response);
        }
        elseif ($e instanceof NotAllowedException){
            return $c['notAllowedHandler']($request, $response);
        }
        elseif ($e instanceof PhpErrorException){
            return $c['phpErrorHandler']($request, $response);
        }
        else {
            return $c['applicationErrorHandler']($request, $response, $e);
        }
    };
};


$c['notFoundHandler'] = function ($c) {
    return function ($request, $response) use ($c) {
        // return $c['response']->withJson(['error'=>'Page not found'],404);
        // Should I use $c['response'] or $response
        return $response->withJson(['error'=>'Page not found'],404);
    };
};
$c['notAllowedHandler'] = function ($c) {
    //Where is $methods coming from?
    return function ($request, $response, $methods) use ($c) {
        return $response
        ->withHeader('Allow', implode(', ', $methods))
        ->withJson(['error'=>'Method must be one of: ' . implode(', ', $methods)],405);
    };
};
$c['phpErrorHandler'] = function ($c) {
    return function ($request, $response) use ($c) {
        return $c['response']->withJson(['error'=>'Critical System Error'],500);
    };
};
$c['applicationErrorHandler'] = function ($c) {
    return function ($request, $response, $e) use ($c) {
        return $response->withJson(['error'=>$e->getMessage()],422);
    };
};


$app = new \Slim\App($c);


$app->post('/test', function (Request $request, Response $response) {
    $rs=someFunctionWhichEitherReturnsArrayOrThrowsException();
    return $response->withJson($rs[0],$rs[1]);
});


$app->options('/{routes:.+}', function ($request, $response) {
    return $response;
});


$app->run();

 

I was partially mistaken.  $e is set in the finally block for a PDOException, but not for any other exceptions.

 

Should I just catch Exception after I catch PDOException, and just throw the exception so it is defined?

try {
    $pdo->beginTransaction();
    //$pdo->prepare('SELECT x FROM invalid_table'); //finally block will have $e set
    throw new Exception();
    return true;
} catch (PDOException $e) {
    //Some logic goes here
    throw true?$e: new Exception;
} catch (Exception $e) {
    throw $e;   //Just done to define $e?
} finally {
    //$e set for PDOException but not Exception?
    syslog(LOG_INFO,isset($e)?'$e is set':'$e is not set');
    if (isset($e) || !$pdo->commit()) {
        syslog(LOG_INFO,'rollBack');
        $pdo->rollBack();
    }
}

 

Do you actually need $e for something? I used it in that code as a way to check for success (it could have been buggy) so you could use a flag to the same end.

$success = false;
try {
	$pdo->beginTransaction();
	throw new Exception();
	return $success = true;
} catch (PDOException $e) {
	// ???
} finally {
	if (!$success || !$pdo->commit()) {
		// ...
	}
}

Do you actually need $e for something? I used it in that code as a way to check for success (it could have been buggy) so you could use a flag to the same end.

 

No I don't.  Thanks, a flag works fine.

 

I am actually returning some data, not true, so will do the following.

            $success=true;
            return [$d,200];

Your call to $pdo->commit() should be in your try block, not the finally block.

 

try {
    $pdo->beginTransaction();
    //insertSomeRecords();
    //Just used to fake a PDOException
    $pdo->prepare('SELECT x FROM invalid_table');
    $pdo->commit();
} catch (PDOException $e) {
    //Some logic goes here
    throw $e;
}
If an exception is thrown the call to commit will be skipped and the transaction will be automatically rolled back.
  • Like 1

Your call to $pdo->commit() should be in your try block, not the finally block.

 

 

The finally block will always be executed, right?  Then wouldn't the following always either commit or rollback?

finally {
    if (!$success || !$pdo->commit()) {
        $pdo->rollBack();
    }
}

Looking at what I did there (being the author of that code), it is a bit odd: normally one would think of the try{} being the normal execution part, the catch{} as the error recovery part, and the finally{} as a optional (if needed) clean-up part. My thinking at the time was probably along the lines of using the try{} for the bulk of the work, the catch{} for altering the work to adapt to an error, and the finally{} as finalizing the work being done (be that a commit or a rollback).

 

The latter makes sense to me, but the former is probably better as a rule of thumb. While the code is functional (...right?) I suggest following kicken's advice.

The reason for using the finally block was that I was catching more than one exception it it slightly reduced the amount of script.  That being said, I agree with you who agrees with kicken which agrees with the way I was originally doing it :)

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.