Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code in try block continues executing after exception?

I am trying to implement Google+ login on my website and am running into an issue. Here is my code (after creating a Google_Client object):

try {
    $client->authenticate($_GET['code']);

    $plus = new \Google_Service_Plus($client);
    $person = $plus->people->get('me');

    $firstName = $person->modelData->name->givenName;

} catch (Google_Auth_Exception $e) {
    $response = array(
        'error' => 'Error: Authentication exception.'
    );
} catch (Exception $e) {
    $response = array(
        'error' => 'Error: Uncaught exception.'
    );
}
  1. $client->authenticate() throws a Google_Auth_Exception if the code passed to it is invalid
  2. If authentication failed, then reading properties from the $person object causes fatal errors
  3. $responseis echo'd out as a JSON-encoded object

The problem is that the try/catch code does not seem to be working properly. When authentication fails due to the code in $_GET['code'] being invalid, the following response is returned from the script:

{"error":"Error: Authentication exception."}

So far so good -- the code in the first catch block was executed.

However, the code in the try block continues to execute in a weird fashion. I say "weird" because in the above form, a bunch of errors (culminating in a fatal error) occur, meaning this line:

$firstName = $person->modelData->name->givenName;

Is still executed! It should not be executed since an exception was thrown on a previous line. If I comment out the above line, the errors are not thrown (again indicating this line is executed, which it shouldn't be).

Here are the errors outputted due to the above line executing after the exception has been thrown:

Notice: Undefined index: modelData in [...]\google-api-php-client-master\src\Google\Model.php on line 78

Notice: Trying to get property of non-object in [...]\ajax_handler.php on line 720 [note: this is the line shown above, where the property is being accessed]

Notice: Trying to get property of non-object in [...]\ajax_handler.php on line 720

Another reason I said "weird" is that if I add this line:

die('dying before reading property');

Right before the above line (where I read a property), no errors occur, BUT the "dying before reading property" text is not output onto the page! This is weird because the script is clearly still executing code in the try block after the error is thrown (since without this die() line, the line reading the property is executed and results in lots of errors being output). As with before, the code in the catch block is still executed and the JSON is output onto the page.

What on earth is going on?

like image 948
Nate Avatar asked May 26 '14 11:05

Nate


2 Answers

PHP is a compiled language. See this question and this answer for an explanation.

Basically, the code is parsed, assembled, and compiled into bytecode before it's executed; what's happening with your script is that the code is invalid. The syntax is correct, so PHP doesn't just outright fail. The issue arises after the object $person is constructed, when you try to access a dynamic property (modelData) that doesn't exist or is inaccessible due to its scope. So the errors you are seeing are because PHP can't find it.

The reason the code doesn't output 'dying before reading property' is because the code isn't actually being executed, so it can't "stop" execution; it's already stopped.

Change

$firstName = $person->modelData->name->givenName;

to

$firstName = $person->name->givenName;

and you should be good to go.

like image 94
klugerama Avatar answered Sep 17 '22 20:09

klugerama


This question and its selected answer keep bothering me. It seems so unlikely that PHP would have executed/parsed/whatever, while an exception was already thrown.

I would rather suggest the code is being run twice. The first time giving the Exception message, and the second time producing the notices.

I suggest you try this:

  • put $testVar = uniqid(); just before try {
  • put echo $testVar; just after try {

When you run the code now you should see a unique ID just before the Exception message, and (my theory) another/different unique ID just before your notices. This would prove the code is being run twice.

About the die("..."); not appearing, I would ask if you really checked this looking in your HTML source, because it could be hidden for some reasong. (eg invisible div)

like image 28
nl-x Avatar answered Sep 18 '22 20:09

nl-x