tags:

views:

105

answers:

6

I am kind of confused about how the below code works. In my head I am imagining each php block being executed as a whole and rendered to HTML. The fact that the first block is kind of incomplete with a hanging brace doesn't play nicely with how I imagine PHP to work. What does the PHP module do when it gets to a PHP closing tag? How is it that code inside the PHP tags can effect the output of plaintext outside of the PHP tags, i.e. only conditionally outputting the form?

I would have thought that to accomplish the below you would have actually had to use an echo statement to conditionally echo the form.

<html>
<head></head>
<body>

<?php
/* if the "submit" variable does not exist, the form has not been submitted - display initial page */
if (!isset($_POST['submit'])) {
?>

    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
    Enter your age: <input name="age" size="2">
    <input type="submit" name="submit" value="Go">
    </form>

<?php
    }
else {
/* if the "submit" variable exists, the form has been submitted - look for and process form data */
    // display result
    $age = $_POST['age'];
    if ($age >= 21) {
        echo 'Come on in, we have alcohol and music awaiting you!';
        }
    else {
        echo 'You're too young for this club, come back when you're a little older';
    }
}
?>

</body>
</html>
+3  A: 

The parts outside of the php tags are treated as literals that are outputted in that part of the program flow.

Bernard Chen
+2  A: 

If the conditional fails, it skips to the end curly-braces within the php block. Everything else is considered a literal that goes straight to the page (as opposed to being considered code).

McAden
A: 

PHP developers frequently encounter the problem with sending headers and cookies after output has been sent to the browser, but that problem can also happen with unintentional output. If whitespace gets inserted after the end of a PHP code block, that can produce unintentional output when that PHP script is included.

Source: http://phpstarter.net/2009/01/omit-the-php-closing-tag/

Sergey Kuznetsov
+3  A: 

Think of it in reverse. The whole document is PHP, with an implicit ?> at the start and an implicit <? at the very end. Then you get these equivalencies:

?>HTML TAGS<?

becomes equivalent to

echo 'HTML TAGS';

In other words, each inverted pair of PHP opening/closing braces encapsulates an echo statement.

Killroy
It's kind of a bad understanding to get into one's head, actually. More like – data outside php tags is not evaluated, but is still part of all control flow statements.
Joel L
Maybe fro ma script writer perspective. 10 years ago I created a PHP-like programming environment, and this is exactly how the compiler/interpreter is implemented. From a compiler-writer perspective this is a pretty good understanding of how things work. Data is evaluated only under special circumstances, such as double quotes. It's really bad to think of data being evaluated generally rather then only in special circumstances.
Killroy
+3  A: 

The PHP manual explains it pretty decently:

...when PHP hits the ?> closing tags, it simply starts outputting whatever it finds (except for an immediately following newline - see instruction separation ) until it hits another opening tag ... but for outputting large blocks of text, dropping out of PHP parsing mode is generally more efficient than sending all of the text through echo() or print()...

Rob Hruska
A: 

+1 Bernard's answer.

You can make this look less strange/broken by using your templating-level control structures like well-formed tags, eg.:

<?php if (!isset($_POST['submit'])) { ?>
    <form method="post" action="<?php echo htmlspecialchars($_SERVER['PHP_SELF']); ?>">
        <label for="age">Enter your age:</label>
        <input name="age" id="age">
        <input type="submit" name="submit" value="Go">
    </form>
<?php } else { ?>
    <?php
        // Read submitted age
        //
        $age= intval($_POST['age']);
    ?>
    <?php if ($age >= 21) { ?>
        Come on in, we have alcohol and music awaiting you!
    <?php } else { ?>
        You're too young for this club, come back when you're a little older.
    <?php } ?>
<?php } ?>

Note the htmlspecialchars around the $_SERVER['PHP_SELF']; — this was a cross-site-scripting hole in the example code. Plus there was an obvious problem with the apostrophes in the last echo.

bobince
Personally I find the code becomes much more readable with short tags enabled. This also enables this syntactic short cut:<input value="<?=$phpvar?>">
Killroy
Yeah, only that short-cut omits the vital `htmlspecialchars`, so it's not that short in the end. I agree that short tags are more readable but it looks like they're on the way out regardless. The idea of moving PHP to XML Processing Instructions was a good one, but unfortunately since they provide no way to inject attribute values you still can't write PHP that's also well-formed XML. So in the end the change to ‘long-tag’ PIs has turned out quite pointless.
bobince