try块中的代码在异常后继续执行?

时间:2014-05-26 11:24:53

标签: php try-catch google-plus

我正在尝试在我的网站上实施Google+登录信息并遇到问题。这是我的代码(创建Google_Client对象后):

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()会抛出Google_Auth_Exception
  2. 如果身份验证失败,则从$person对象读取属性会导致致命错误
  3. $response作为JSON编码对象回显出来
  4. 问题是try/catch代码似乎无法正常工作。如果由于$_GET['code']中的代码无效而导致身份验证失败,则会从脚本返回以下响应:

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

    到目前为止一直很好 - 执行了第一个catch块中的代码。

    然而,try块中的代码继续以奇怪的方式执行。我说“怪异”,因为在上面的形式中,出现了一堆错误(最终导致致命错误),这意味着这一行:

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

    仍然执行!它应该执行,因为在前一行上抛出了异常。如果我注释掉上面的行,则不会抛出错误(再次表明该行已执行,它不应该执行)。

    以下是在抛出异常后执行的上述行输出的错误:

      

    注意:未定义的索引:第78行的[...] \ google-api-php-client-master \ src \ Google \ Model.php中的modelData

         

    注意:尝试在第720行的[...] \ ajax_handler.php中获取非对象的属性[注意:这是上面显示的行,其中正在访问该属性]

         

    注意:尝试在第720行的[...] \ ajax_handler.php中获取非对象的属性

    我说“怪异”的另一个原因是,如果我添加这一行:

    die('dying before reading property');
    

    在上面的行(我读取属性)之前,没有错误发生,但“读取属性前死亡”文本没有输出到页面上!这很奇怪,因为在抛出错误之后脚本显然仍然在try块中执行代码(因为没有这个die()行,读取属性的行被执行并导致输出大量错误)。与之前一样,catch块中的代码仍然执行,JSON输出到页面上。

    到底是怎么回事?

2 个答案:

答案 0 :(得分:6)

PHP是一种编译语言。有关说明,请参阅this questionthis answer

基本上,代码在执行之前被解析,组装和编译成字节码;您的脚本发生的是代码无效。语法是正确的,因此PHP不会完全失败。在构造对象$person之后,当您尝试访问由于其范围而不存在或无法访问的动态属性(modelData)时,会出现此问题。所以你看到的错误是因为PHP无法找到它。

代码输出'dying before reading property'的原因是因为代码实际上没有被执行,所以它不能“停止”执行;它已经停止了。

更改

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

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

你应该好好去。

答案 1 :(得分:1)

这个问题及其选定的答案一直困扰着我。

,似乎不太可能PHP执行/解析/等等

我宁愿建议代码运行两次。第一次发出Exception消息,第二次发出通知。

我建议你试试这个:

  • $testVar = uniqid();
  • 之前放置try {
  • echo $testVar;
  • 之后放置try {

现在运行代码时,您应该在Exception消息之前看到一个唯一的ID,并且(我的理论)在您的通知之前看到另一个/不同的唯一ID。这将证明代码正在运行两次。

关于die("...");没有出现,我会问你是否真的在HTML源代码中查看了这个内容,因为它可能会隐藏起来。 (例如看不见的div)