I'm doing an experiment, an html preprocessor like SLIM or Jade.
This is the PHP code that seems right:
nav
ul id: "test"
li
@<?= $Var; ?>
li
@About
li
@Contact
This is the expected pre-processed html (yes, $Var == "Test"):
nav
ul id: "test"
li
@Test
li
@About
li
@Contact
However, in the browser I get this wrong text as the pre-processor html:
nav
ul id: "test"
li
@Test li
@About
li
@Contact
Lastly, there are two ways to make it correct.
Adding the break line manually:
nav ul id: "test" li @<?= $Var . "\n"; ?> li @About li @Contact
Writing a space after the PHP closing tag (??).
Why is the first case, <?= $Var; ?>
, ignoring the line feed after the closing PHP tag? I couldn't really find anything since google brought too many results about why you should ignore the closing tag for every search I did and not what I wanted to find.
Update:
Looking at the zend language scanner src, it would seem that my "hunch" was correct: the
T_CLOSE_TAG
token would appear to possibly contain a newline char. What's more, It'd also seem that a closing semi-colon for the last statement in a script that contains a closing tag is optional...Just look for
T_CLOSE_TAG
in the zend_language_scanner.c and zend_language_scanner.l files hereI'm currently scanning the source of the Zend engine, to be sure, but I'd guess that, since the last char(s) of the code you posted are, simply, the closing tag (
?>
), it's PHP that is generating the output. Seeing as you're not telling PHP to output a line-feed, it stands to reason that PHP won't add a new line to whatever you're echoing.The line-feed char that follows the closing tag is, of course, ignored by PHP, but for some reason, PHP does indeed seem to consume that line feed. I'm looking at the C code that parses your PHP script, but I'm thinking it might use new-lines, whitespace, comma's semi-colons and all that as tokens to chunk the input into nodes.
Seeing as the closing tag
?>
is a bona-fide token, and part of the PHP grammar, It could well be that this is where the line-feed is effectively consumed by the engine, and why it's not part of the output.By adding a space char after the closing tag, The space might be consumed, but the new-line isn't, so that might be why you're still seeing the line-feed show up.
I've also tried adding 2 line feeds to some test code, and indeed: the output showed only 1 new line:
Output:
So it would seem that my suspicions might hold water.
However, all things considered, lest you want to go hacking away at the Zend engine source, adding the line-feed manually isn't that much of a hasstle. In fact, it's a good way to ensure the correct line-feeds are generated:
Suppose you wrote some code, on a healty *NIX system, where line-feeds are, to all intents and purposes represented by the
\n
escape sequence, adding that char manually might not yield the desired output on, say, a windows system (which uses\r\n
), Apple systems use\r
...PHP has a constant to ensure you're churning out the correct line-feeds, depending on the platform your code is running on:
PHP_EOL
. Why not use that:In case you're wondering: yes, that is
$bar
commaPHP_EOL
you're seeing there. Why? Think ofecho
or<?=
as C++'sCOUT
, it's a construct that just pushes whatever you're throwing at it to the output stream, weather it be a concatenated string, or just a comma separated list of variables: it doesn't care.Now, the following section of my answer is going slightly off-topic, but it's just something so basic, and self-evident, and yet many people are so un-aware of it, that I can't resist the temptation of explaining a thing or two about string concatenation.
PHP, and most any language I know of, doesn't care about how many vars/vals it has to push to the output stream. It's what it's for. PHP, and again: most languages, does care about concatenation of strings: A string is sort of a constant value. You can't just make a string longer when the mood takes you. A series of chars have to be stored in memory, memory that has to be allocated to accommodate a longer string. What concatenation effectively does (best case scenario), is this:
Whereas, in a lot of cases, what actually happens is:
An example of the first case:
Could translate to the following C code:
However, by simply doing this:
What you're actually doing is:
And as if that weren't enough, just think what this code implies:
Yes, sure enough:
Now I haven't even gotten to the real concatenation nightmares yet (don't worry, I'm not going to either). Stuff like
$foo = 'I ' . ' am '. 'The'. ' ' .$result.' of some'.1.' with a dot'.' fetish';
. Look at it, there's variables in there, that might be anything (arrays, objects, huuuge strings..., there's an integer in there, too... replace the dots with comma's and pushing it to theecho
construct just is so much easier than even begin contemplating writing the code required to correctly concatenate all of these values together...Sorry for drifting off here slightly, but seeing as this is, IMO, so basic, I feel as though everyone should be aware of this...