PHP中的卷曲括号语法?

时间:2017-01-06 22:10:33

标签: php

我刚刚发现这是在goto的评论中浏览PHP文档:http://php.net/manual/en/control-structures.goto.php#92763

我的问题是,为什么这有效?

testing: {
    process: {
        die('Called');
    }
}

// Displays 'Called'.
goto process;

// Doesn't work, syntax error
goto testing.process;

这个语法叫做什么,它是否曾在PHP开发中使用过?

我似乎无法找到有关此语法的任何文档,也没有任何示例。

非常感谢有关该主题的任何知识!

3 个答案:

答案 0 :(得分:2)

这是一个简单的goto

我有时会在某些边缘情况下使用它(通常是为了避免嵌套if/else)。

但必须非常小心地使用它。

我只用它来设置脚本的结尾,这通常是一个简单的return

永远不要用它来做复杂的事情,否则你的代码会很快变得混乱。

以下是PHP文档中的参考:goto

这是一个具体的实现,其中使用goto是必要的,以使代码可读和清洁:

/**
 * @param \Exception $e
 *
 * @return bool|string Returns false in "production" if something goes wrong.
 *                     May return "retry" if rate limit is reached
 *
 * @throws ApiConnection  Only in dev and test environments
 * @throws Authentication Only in dev and test environments
 * @throws Card           Only in dev and test environments
 * @throws InvalidRequest Only in dev and test environments
 * @throws RateLimit      Only in dev and test environments
 */
private function handleException(\Exception $e)
{
    // If we received a rate limit exception, we have to retry with an exponential backoff
    if ($e instanceof RateLimit) {
        // If the maximum number of retries is already reached
        if ($this->retries >= $this->maxRetries) {
            goto raise;
        }

        // First, put the script on sleep
        sleep($this->wait);

        // Then we have to increment the sleep time
        $this->wait += $this->wait;

        // Increment by 1 the number of retries
        ++$this->retries;

        return 'retry';
    } elseif ($e instanceof Card) {
        if ('dev' === $this->environment || 'test' === $this->environment) {
            throw $e;
        }

        return false;
    }

    // \Stripe\Error\Authentication, \Stripe\Error\InvalidRequest and \Stripe\Error\ApiConnection are raised immediately
    raise:
    $body = $e->getJsonBody();
    $err = $body['error'];
    $message = '[' . $e->getHttpStatus() . ' - ' . $e->getJsonBody()['error']['type'] . '] ' . $e->getMessage();
    $context = [
        'status' => $e->getHttpStatus(),
        'type' => isset($err['type']) ? $err['type'] : '',
        'code' => isset($err['code']) ? $err['code'] : '',
        'param' => isset($err['param']) ? $err['param'] : '',
        'request_id' => $e->getRequestId(),
        'stripe_version' => $e->getHttpHeaders()['Stripe-Version']
    ];

    if (null === $this->logger) {
        $this->logger->error($message, $context);
    }

    if ('dev' === $this->environment || 'test' === $this->environment) {
        throw $e;
    }

    return false;
}

此代码管理Stripe SDK引发异常的情况。

如您所见,如果达到最大重试次数,代码会直接“跳转”到raise标记。

这是我维护的Symfony的捆绑包。其完整代码可用here on GitHub

答案 1 :(得分:2)

goto文档中,target:语法不会被调用,它只是表示goto能够跳转到的目标。

除了属于该目标的代码之外,花括号本身并不代表任何东西。与this comment中一样,大括号只会使目标语法更清晰。

目标只与goto有关。目标不是(也不可能是)变量而不是对象。

PHP中的.语法是一个字符串连接运算符,因为testingprocess目标不是字符串,它会抛出一个错误,说明.是意外的

由于它们不是对象,您将无法goto testing->process;,因为testing不拥有processtesting只是另一个process的目标其中的目标是{1}}。您只能拨打goto testing;Called仍会输出。

与其他人一样,请不要使用goto。它会有所帮助更有害。

答案 2 :(得分:2)

PHP中的大括号仅用于将语句分组到块中,该块可用于需要单个语句的位置。例如,当ifwhile的正文是多个语句时,您需要使用大括号对它们进行分组。

除此之外,它们完全是可选的,对代码的运行方式没有影响。但是编辑会将代码缩进到括号内,因此它可以用于自我记录目的,以便一起显示相关的语句。

这就是他们在您引用的示例中使用它们的原因。正如文中所说:

  

如果您不喜欢悬挂在其周围的野生标签,可以在此构造中自由使用牙箍,从而创建略微更清洁的外观。

这是他使用它们的唯一目的,这只是他的个人风格。

这不是一个常见的习惯用法(goto一般不常见,因此很少需要声明标签),而且我不知道它的任何特定名称。