简体   繁体   中英

Curly brace syntax in PHP?

I just discovered this browsing the PHP documentation inside a comment for goto : http://php.net/manual/en/control-structures.goto.php#92763

My question is, why does this work?

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

// Displays 'Called'.
goto process;

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

What is this syntax called and is it ever utilized in PHP development?

I can't seem to find any documentation about this syntax, nor any examples.

Any knowledge on the subject would be much appreciated!

This is a simple goto .

I've used it sometimes in some edge cases (often to avoid nested if/else ).

But it has to be used very carefully.

I used it only to set the end of the script that were often a simple return .

Never use it to do complex things or your code will become messy very fast.

Here is the reference in the PHP documentation: goto

This is a concrete implementation where the use of goto was necessary to make the code readable and clean:

/**
 * @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;
}

This code manages the case of the raising of an exception by the Stripe SDK.

As you can see, if the max number of retries is reached, the code directly "jumps" to the raise tag.

This is a bundle for Symfony I maintain. Its full code is available here on GitHub .

In the goto documentation the target: syntax isn't called anything, it just denotes a target for a goto to be able to jump to.

The curly braces don't signify anything themselves, other than the code within belongs to that target . As in this comment , the braces just make the target syntax cleaner.

The target only has anything to do with the goto. The target isn't (and can't be) a variable and isn't an object.

The . syntax in PHP is a string concatenation operator, since the testing and process targets aren't strings, it throws an error saying the . was unexpected.

Since they aren't objects either you wouldn't be able to goto testing->process; since testing doesn't own process , testing is just a target with another process target within it. You can call just goto testing; and Called will still be output.

Like everyone else is saying, please don't use goto . It's more harmful that it would be helpful.

Braces in PHP are used simply to group statements into a block, which can be used in places where a single statement is required. For instance, when the body of if or while is multiple statements, you need to use braces to group them.

Other than that, they're totally optional and have no effect on how the code runs. But editors will indent the code inside braces, so it can serve a self-documentation purpose to show related statements together.

That's why they're being used in the example you referenced. As the text says:

if you are not a fan of wild labels hanging around you are free to use braces in this construct creating a slightly cleaner look.

That's the only purpose he has in using them, it's just his personal style.

It's not a common idiom ( goto in general is not common, so statement labels are rarely needed), and I'm not aware of any particular name for it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM