Fra*_*cia 9 html php preprocessor line-breaks
我正在做一个实验,一个像SLIM或Jade这样的html预处理器.
这是似乎正确的PHP代码:
nav
ul id: "test"
li
@<?= $Var; ?>
li
@About
li
@Contact
Run Code Online (Sandbox Code Playgroud)
这是预期的预处理html(是的,$ Var =="Test"):
nav
ul id: "test"
li
@Test
li
@About
li
@Contact
Run Code Online (Sandbox Code Playgroud)
但是,在浏览器中我得到这个错误的文本作为预处理器html:
nav
ul id: "test"
li
@Test li
@About
li
@Contact
Run Code Online (Sandbox Code Playgroud)
最后,有两种方法可以使其正确.
手动添加分隔线:
nav
ul id: "test"
li
@<?= $Var . "\n"; ?>
li
@About
li
@Contact
Run Code Online (Sandbox Code Playgroud)在PHP结束标记之后写一个空格(??).
为什么是第一种情况,<?= $Var; ?>忽略关闭PHP标记后的换行符?我真的找不到任何东西,因为谷歌带来了太多的结果,为什么你应该忽略我做的每一次搜索的结束标记,而不是我想要找到的.
Eli*_*gem 10
更新:
看看zend语言扫描程序src,看起来我的"预感"是正确的:T_CLOSE_TAG令牌似乎可能包含换行符.更重要的是,在脚本中包含结束标记的最后一个语句的结束分号似乎是可选的......
<ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"){NEWLINE}? {
ZVAL_STRINGL(zendlval, yytext, yyleng, 0); /* no copying - intentional */
BEGIN(INITIAL);
return T_CLOSE_TAG; /* implicit ';' at php-end tag */
}
Run Code Online (Sandbox Code Playgroud)
只需T_CLOSE_TAG在这里查看zend_language_scanner.c和zend_language_scanner.l文件即可
我当前正在扫描Zend引擎的源代码,但是我猜想,因为你发布的代码的最后一个字符是简单的结束标记(?>),它是生成的PHP输出.因为你没有告诉PHP输出换行符,所以PHP不会在你回复的任何内容中添加新行.
当然,PHP会忽略关闭标记后面的换行符,但由于某种原因,PHP确实似乎消耗了该换行符.我正在查看解析PHP脚本的C代码,但我认为它可能会使用换行符,空格,逗号的分号以及所有这些作为标记来将输入分块到节点中.
看作结束标记?>是一个真正的标记,也是PHP语法的一部分,很可能这就是引擎有效消耗换行的原因,以及为什么它不是输出的一部分.
通过在结束标记之后添加空格字符,可能会消耗空间,但新行不会消耗,因此这可能是您仍然看到换行显示的原因.
我也尝试在一些测试代码中添加2个换行符,实际上:输出只显示了1个新行:
foo:
<?= $bar; ?>
foobar
Run Code Online (Sandbox Code Playgroud)
输出:
foo:
bar
foobar
Run Code Online (Sandbox Code Playgroud)
所以看来我的怀疑可能会持水.
但是,考虑到所有事情,以免你想要在Zend引擎源上进行攻击,手动添加换行并不是一个很好的任务.实际上,这是确保生成正确换行的好方法:
假设您在一个健康的*NIX系统上编写了一些代码,其中换行符是由\n转义序列表示的所有意图和目的,添加该字符串,手动可能无法在Windows系统(使用\r\n)上产生所需的输出,Apple系统使用\r...
PHP有一个常量来确保您生成正确的换行符,具体取决于您的代码运行的平台上:PHP_EOL.为什么不使用它:
<?= $bar, PHP_EOL; ?>
Run Code Online (Sandbox Code Playgroud)
万一你想知道:是的,那是你看到的$bar 逗号 PHP_EOL.为什么?想象一下,echo或者<?=作为C++ COUT,它是一个构造,它只是将你投掷的任何内容推送到输出流,它是一个连接的字符串,或者只是一个逗号分隔的变量列表:它并不关心.
现在,我的回答以下部分稍微会偏离主题,但它只是一些这样基本的,不言而喻的,但仍然有许多人是如此未意识到这一点,我无法抗拒解释的诱惑关于字符串连接的一两件事.
PHP,以及我所知道的大多数语言,并不关心它有多少vars/val来推送到输出流.这就是它的用途.PHP,以及:大多数语言,都关心字符串的连接:字符串是一种常量值.当心情带你时,你不能只让字符串更长.一系列字符必须存储在内存中,内存必须分配以容纳更长的字符串.有效连接的最佳情况(最佳情况)是:
然而,在很多情况下,实际发生的是:
第一种情况的一个例子:
$str1 = 'I am string constant 1';
$str2 = ' And I\'ll be concatenated';
$str1 .= $str2;
Run Code Online (Sandbox Code Playgroud)
可以转换为以下C代码:
char *str1, *str2;
//allocate mem for both strings, assign them their vals
str1 = realloc(str1,(strlen(str1) + strlen(str2)+1));//re-allocate mem for str1
strncat(str1, str2, strlen(str2);//concatenate str2 onto str1
Run Code Online (Sandbox Code Playgroud)
但是,只需这样做:
$str3 = $str1 . $str2;
Run Code Online (Sandbox Code Playgroud)
你实际在做的是:
char *str3 = malloc((strlen(str1) + strlen(str2) + 1)*sizeof(char));
strcpy(str3, str1);//copy first string to newly allocated memory
strcat(str3, str2);//concatenate second string...
Run Code Online (Sandbox Code Playgroud)
并且好像这还不够,只要想想这段代码意味着什么:
$str1 = $str2 . $str1;
Run Code Online (Sandbox Code Playgroud)
是的,果然:
char *str3 = malloc((strlen(str1) + strlen(str2) + 1)*sizeof(char));
strcpy(str3, str2);//copy seconds string to start of new string
strcat(str3, str1);//add first string at the end
free(str1);//free memory associated with first string, because we're reassigning it
str1 = str3;//set str1 to point to the new block of memory
Run Code Online (Sandbox Code Playgroud)
现在我还没有真正的串联噩梦(不用担心,我也不会去).好像的东西$foo = 'I ' . ' am '. 'The'. ' ' .$result.' of some'.1.' with a dot'.' fetish';.看看它,那里有变量,可能是任何东西(数组,对象,huuuge字符串......,那里也有一个整数......用逗号代替点并将它推到echo构造中就这么容易了甚至开始考虑编写正确连接所有这些值所需的代码...
抱歉稍微偏离这里,但看到这是,IMO,如此基本,我觉得好像每个人都应该意识到这一点......