在PHP中,输出缓冲区打印到哪里?打印什么东西?

jam*_*her 3 php buffer output semantics

PHP有许多不同的打印方式,我不明白它们之间的区别.至少有以下几点:

  • stdout和stderr.这些可以表示为php://stdoutphp://stderr.也有常数STDOUTSTDERR,我认为这指的是同样的事情.到现在为止还挺好; 这些是标准的.
  • php://output.这是什么?它去哪儿了?它是同义词php://stdout还是别的什么?文档说它写"输出缓冲机制",但我不知道此缓冲区的内容在那之后.
  • printecho.文档说这些打印到php://output.它们都是语言结构,但在猜测时,不同之处在于它print是一个表达式,但它echo是一个声明.
  • printf还有很多朋友.这些都去了php://output吗?
  • 逃跑.有许多替代语法用于转义,但我猜他们都有相同的语义.但是什么是语义?转义的文本打印到哪里?还来php://output?目前,我理解?>foo<?php为语法糖echo 'foo';; 它是否正确?

有更多的输出方式吗?究竟有什么区别?哪些设置和环境会影响他们的行为?

eli*_*f21 9

首先,stdin和stdout是大多数语言都具有的标准输入和输出流.如果你通过控制台运行php,你可以创建一个这样的脚本:

$input = fopen("php://stdin", "r");
$line = trim(fgets($input));

echo $line;
Run Code Online (Sandbox Code Playgroud)

要么

$line = trim(fgets(STDIN));

echo $line;
Run Code Online (Sandbox Code Playgroud)

这些脚本将打开标准控制台输入,并允许您输入由返回终止的输入.

现在从命令行'php:// stdout'和'php:// output'功能非常相似,假设您默认没有输出缓冲,并且都会向控制台提供标准输出.通过做类似的事情:

$out = fopen("php://stdout", "w");
fwrite($out, "Hello World!");
Run Code Online (Sandbox Code Playgroud)

要么

$out = fopen("php://output", "w");
fwrite($out, "Hello World!");
Run Code Online (Sandbox Code Playgroud)

这两个都会输出Hello World!按预期到控制台.

现就输出缓冲而言,它在php配置文件中默认设置为0(意味着它被禁用).输出缓冲是一种"阻止"输出的方式,无论是写入控制台还是浏览器.如果您使用ob_start函数打开输出缓冲,则您的输出都不会转到控制台/浏览器.相反,它将被放入缓冲区并等待缓冲区达到其最大容量(或直到您手动刷新它),然后它将缓冲区内容转储到stdout.

打印和回声.这些不是真正的函数,它们是语言结构,其中echo不返回任何内容,print始终返回1.两者之间的主要区别在于echo可以打印由逗号分隔的多个字符串.

print和echo都打印到输出缓冲区,但由于默认情况下输出缓冲被禁用,它们似乎直接输出到控制台/浏览器.

现在至于php:// output和STDOUT之间的区别.如果打开输出缓冲,则只有明显的区别.如果它打开,那么stdout输出仍将转到控制台/浏览器的标准输出,但php://输出将转到缓冲区,直到缓冲区达到它的容量或手动刷新缓冲区.这个例子说明了不同之处:

<?php
    $out1 = fopen("php://stdout", 'w');
    $out2 = fopen("php://output", "w");
    ob_start();   //enable output buffering
    echo "This is an echo\n";
    print "This is a print\n";
    printf("%d", 52);
    echo "\n";
    fwrite($out1, "Hello World!");
    fwrite($out2, "\nGoodbye World!");
    ob_end_clean(); //turn off output buffering and get rid of it's contents without printing them
?>
Run Code Online (Sandbox Code Playgroud)

请注意如何只有Hello World!输出而不是此脚本中的其余输出语句.如果我们注释掉ob*语句,那么我们会看到所有其他输出都放在输出缓冲区中.如果我们在脚本末尾使用ob_end_flush()而不是Hello World!然后是输出缓冲区的所有输出,按顺序放入缓冲区.此外,从这个例子我们也可以看到printf也打印到输出缓冲区(可能使用echo或print的底层功能),我假设这是所有其他格式化函数的工作方式,但不引用我在那.

就你所指的逃避而言,这通常是为了有条件地显示html,或者你有一些你不想硬编码的东西.例如考虑:

<select>
<? foreach($array as $option){ ?>
    <option value="<?=$option?>"><?=$option?></option>
<? }?>
</select>
Run Code Online (Sandbox Code Playgroud)

此代码可用于为没有硬编码值的选择输出选项数组,而无需使用写回显或打印或打印语句(注意通过语法间接使用echo).

令人惊讶的是,此输出也会写入输出缓冲区,并包含您在此区域中输入的任何空格,但前提是您在控制台(浏览器以不同方式解释空白).此外,转义字符如\n,\ t等等在此上下文中没有任何意义,并且完全按照它们的方式进行解释.通过将上面的代码修改为:

<?php
$out1 = fopen("php://stdout", 'w');
$out2 = fopen("php://output", "w");
//ob_start();
echo "This is an echo\n";
print "This is a print\n";
printf("%d", 52);
echo "\n";
?>
Jelly Bean
<?php
fwrite($out1, "Hello World!");
fwrite($out2, "\nGoodbye World!");
//ob_end_clean();
?>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的那样,当输出缓冲语句被注释掉时,会打印Jelly Bean,但如果您在Jelly Bean中注释它们,则不会出现在输出中.再次,如果取消注释ob*语句并使最后一个语句ob_end_flush(),您将看到缓冲区输出到stdout的所有输入,按照它放入缓冲区的顺序.