我刚刚发现这是在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开发中使用过?
我似乎无法找到有关此语法的任何文档,也没有任何示例。
非常感谢有关该主题的任何知识!
答案 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中的.
语法是一个字符串连接运算符,因为testing
和process
目标不是字符串,它会抛出一个错误,说明.
是意外的
由于它们不是对象,您将无法goto testing->process;
,因为testing
不拥有process
,testing
只是另一个process
的目标其中的目标是{1}}。您只能拨打goto testing;
,Called
仍会输出。
与其他人一样,请不要使用goto
。它会有所帮助更有害。
答案 2 :(得分:2)
PHP中的大括号仅用于将语句分组到块中,该块可用于需要单个语句的位置。例如,当if
或while
的正文是多个语句时,您需要使用大括号对它们进行分组。
除此之外,它们完全是可选的,对代码的运行方式没有影响。但是编辑会将代码缩进到括号内,因此它可以用于自我记录目的,以便一起显示相关的语句。
这就是他们在您引用的示例中使用它们的原因。正如文中所说:
如果您不喜欢悬挂在其周围的野生标签,可以在此构造中自由使用牙箍,从而创建略微更清洁的外观。
这是他使用它们的唯一目的,这只是他的个人风格。
这不是一个常见的习惯用法(goto
一般不常见,因此很少需要声明标签),而且我不知道它的任何特定名称。