2013-12-16 44 views
3

PHP有很多不同的打印方式,我不明白它們之間的區別。至少有以下幾點:在PHP中,輸出緩衝區在哪裏打印?什麼東西打印到它?

  • stdout和stderr。這些可以表示爲php://stdoutphp://stderr。還有常數STDOUTSTDERR,我認爲這些指的是相同的東西。到現在爲止還挺好;這些都是標準的。
  • php://output。這是什麼?它在哪裏?它是php://stdout還是別的什麼的同義詞? The docs說它寫入「到輸出緩衝機制」,但我不知道這個緩衝區的內容在那之後。
  • printechoThe docs說這些打印到php://output。它們都是語言結構,但有人猜測,區別在於print是一個表達式,但echo是一個語句。
  • printf和很多朋友。做這些也都去php://output
  • Escaping。有很多逃避的替代語法,但我猜他們都具有相同的語義。但是什麼是語義?轉義文本在哪裏打印?也來php://output?目前,我知道?>foo<?phpecho 'foo';的語法糖;它是否正確?

有沒有更多的輸出方式?究竟有什麼區別?哪些設置和環境影響他們的行爲?

+0

這似乎是S.O – 2013-12-16 19:14:15

+0

@Dagon offtopic我不知道你的意思。 – jameshfisher

回答

8

首先,stdin和stdout是大多數語言的標準輸入和輸出流。如果你運行PHP雖然控制檯,您可以創建這樣一個腳本:

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

echo $line; 

$line = trim(fgets(STDIN)); 

echo $line; 

這些腳本都將打開標準控制檯輸入,並允許你輸入輸入被終止返回。

現在從命令行'php:// stdout'和'php:// output'函數非常類似,假設您默認情況下沒有輸出緩衝,並且都會將標準輸出提供給控制檯。這樣做是這樣的:

$out = fopen("php://stdout", "w"); 
fwrite($out, "Hello World!"); 

$out = fopen("php://output", "w"); 
fwrite($out, "Hello World!"); 

的這兩個將輸出的Hello World!按預期方式到控制檯。

現在就輸出緩衝而言,它在php配置文件中默認設置爲0(意味着它被禁用)。無論輸出緩衝是寫入控制檯還是瀏覽器,輸出緩衝都是「阻止」輸出的一種方式。如果您使用ob_start函數打開輸出緩衝,則不會有任何輸出會進入控制檯/瀏覽器。相反,它會被放入緩衝區並等待緩衝區達到最大容量(或直到手動刷新),然後將緩衝區內容轉儲到stdout。

打印並回顯。這些都不是真正的函數,它們是語言結構,其中echo不返回任何內容,print總是返回1.兩者之間的主要區別在於echo可以打印由逗號分隔的多個字符串。

打印和回顯打印到輸出緩衝區,但由於默認情況下輸出緩衝被禁用,它們似乎直接輸出到控制檯/瀏覽器。

現在至於php://輸出和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 
?> 

請注意只有Hello World!是輸出而不是此腳本中的其餘輸出語句。如果我們註釋掉ob *語句,而不是看到所有其他輸出都放在輸出緩衝區中。如果我們在腳本的末尾使用了ob_end_flush(),我們會使用Hello World!隨後是輸出緩衝區中的所有輸出,按順序放入緩衝區。此外,從這個例子中,我們也可以看到printf也打印到輸出緩衝區(可能使用echo或print的底層功能),我假設所有其他格式化函數都可以工作,但不引用我在那。

就你所指的轉義而言,通常這樣做是爲了有條件地顯示html,或者當你有一些你不想硬編碼的東西時。例如考慮:

<select> 
<? foreach($array as $option){ ?> 
    <option value="<?=$option?>"><?=$option?></option> 
<? }?> 
</select> 

該代碼可以用來輸出一組選項的選擇,而不硬編碼值,並且無需使用write回聲或打印或打印語句(注意回聲通過間接使用句法 )。

令人驚訝的是,這個輸出也被寫入到輸出緩衝區,並且只有當你在控制檯(瀏覽器以不同的方式解釋空白)時,你纔會在這個區域輸入任何空格。而且,\ 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(); 
?> 

正如你可以看到,當輸出緩衝語句被註釋掉果凍豆印,但如果你在果凍豆評論他們回來沒有出現在輸出。同樣,如果您取消註釋ob *語句並創建最後一個語句ob_end_flush(),則會將緩衝區輸出中的所有輸入按照放入緩衝區的順序看到stdout。

+0

奇妙的,實質性的答案,謝謝!回家的要點:'STDIN == fopen(「php:// stdin」,「r」)'等; 'php:// output'只是一個標準緩衝區,最終寫入'php:// stdout';和'?> Jelly Bean <?php'實際上可以理解爲'echo Jelly Bean的語法糖;'。 – jameshfisher