การใช้ ob_start () ใน PHP คืออะไร?


298

จะถูกob_start()ใช้สำหรับoutput bufferingเพื่อให้ส่วนหัวเป็น buffered และไม่ได้ส่งไปยังเบราว์เซอร์? ฉันกำลังทำความเข้าใจที่นี่? ถ้าไม่เช่นนั้นทำไมเราควรใช้ob_start()?

คำตอบ:


481

คิดถึง ob_start()พูดว่า "เริ่มจดจำทุกสิ่งที่ปกติแล้วจะได้ผลลัพธ์ แต่ยังไม่ได้ทำอะไรกับมันเลย"

ตัวอย่างเช่น:

ob_start();
echo("Hello there!"); //would normally get printed to the screen/output to browser
$output = ob_get_contents();
ob_end_clean();

มีฟังก์ชั่นอื่นอีกสองอย่างที่คุณมักจะจับคู่กับ: ob_get_contents()ซึ่งโดยทั่วไปจะให้สิ่งที่คุณ "บันทึก" ไว้ในบัฟเฟอร์ตั้งแต่เปิดใช้ob_start()แล้วob_end_clean()หรือหรือob_flush()ซึ่งหยุดบันทึกสิ่งและยกเลิกสิ่งที่ถูกบันทึกหรือหยุดการบันทึก และส่งออกทั้งหมดในครั้งเดียวตามลำดับ


55
คำอธิบายที่ดี ฉันจะไปอีกขั้นหนึ่งแล้วแทนที่ob_get_contents()ด้วยob_get_clean()และลบob_end_clean()เนื่องจากจะob_get_clean()ทำหน้าที่ทั้งสองอย่างเป็นหลัก การอ้างอิง: php.net/manual/en/function.ob-get-clean.php (PHP 4> = 4.3.0, PHP 5)
Con Antonakos

ฉันถือว่าการบัฟเฟอร์เอาต์พุตต้องเปิดใช้งานในไฟล์. ini เพื่อเรียกใช้ob_start();งานถูกต้องหรือไม่ จะเกิดอะไรขึ้นหากไม่ได้เปิดใช้งาน
Kevin Wheeler

5
@Riley Dutton คุณไม่ได้บอกว่าทำไม ob_start () จึงถูกใช้
Vishnu R Nair

มีปัญหาเดียวกันหลังจากแก้ไขรหัสของฉันด้วยob_end_cleanมันใช้งานได้เหมือนมีเสน่ห์! ขอบคุณ @Riley Dutton
Martins

160

ฉันใช้สิ่งนี้เพื่อให้ฉันสามารถแยก PHP ด้วย HTML จำนวนมาก แต่ไม่สามารถแสดงผลได้ มันช่วยฉันจากการจัดเก็บเป็นสตริงที่ปิดการใช้งานการเข้ารหัสสี IDE

<?php
ob_start();
?>
<div>
    <span>text</span>
    <a href="#">link</a>
</div>
<?php
$content = ob_get_clean();
?>

แทน:

<?php
$content = '<div>
    <span>text</span>
    <a href="#">link</a>
</div>';
?>

1
สามารถใช้เป็นวิธีหนึ่งในการมีหน้า html หลายหน้าภายในหนึ่ง PHP และเรียกพวกเขาผ่าน GET หรือไม่
joshkrz

1
ฉันคิดอย่างนั้น แต่มันฟังดูไม่ดีนัก จะเป็นการดีกว่าถ้าจะโหลดจากแม่แบบที่แยกต่างหาก
JD Isaacks

1
โปรดทราบว่าเทคนิคนี้ใช้ob_get_clean()ไม่ใช่ ob_end_clean()
Blazemonger

11
ไม่เคยคิดเลยว่านี่เป็นวิธีที่พัฒนา IDE ง่ายอย่างไม่น่าเชื่อ! นอกจากนี้ฉันยังไม่จำเป็นต้องใช้ Javascript หรือ HTML เป็นสตริงใน PHP ของฉันตลอดเวลาเพื่อหลบหนี \ "ฯลฯ ซึ่งน่ารำคาญ
J-Dizzle

1
ภาพของคุณให้ภาพที่ชัดเจนเกี่ยวกับประโยชน์ของการใช้ ob_start
klewis

86

คำตอบที่ยอมรับได้ที่นี่อธิบายถึงสิ่งที่ob_start()ไม่ - ทำไมมันถูกใช้ (ซึ่งเป็นคำถามที่ถาม)

ตามที่ระบุไว้ที่อื่นob_start()สร้างบัฟเฟอร์ที่เขียนไป

แต่ไม่มีใครบอกว่าเป็นไปได้ที่จะสแต็คบัฟเฟอร์หลาย ๆ อันใน PHP ดูที่ob_get_level ()

ว่าทำไม ....

  1. การส่ง HTML ไปยังเบราว์เซอร์ในกลุ่มที่มีขนาดใหญ่ขึ้นจะทำให้ได้รับประโยชน์ด้านประสิทธิภาพจากการลดค่าใช้จ่ายของเครือข่าย

  2. การส่งข้อมูลออกจาก PHP ในกลุ่มที่ใหญ่ขึ้นจะช่วยเพิ่มประสิทธิภาพและความสามารถโดยลดจำนวนการสลับบริบทที่จำเป็น

  3. การส่งข้อมูลจำนวนมากไปยัง mod_gzip / mod_deflate จะให้ประโยชน์ด้านประสิทธิภาพซึ่งการบีบอัดอาจมีประสิทธิภาพมากกว่า

  4. การบัฟเฟอร์เอาต์พุตหมายความว่าคุณยังคงสามารถจัดการส่วนหัว HTTP ในภายหลังในรหัส

  5. การล้างบัฟเฟอร์อย่างชัดเจนหลังจากเอาท์พุท [head] .... [/ head] สามารถอนุญาตให้เบราว์เซอร์เริ่ม marshaling ทรัพยากรอื่น ๆ สำหรับหน้าก่อนที่สตรีม HTML จะเสร็จสมบูรณ์

  6. การจับเอาท์พุทในบัฟเฟอร์หมายความว่ามันสามารถเปลี่ยนเส้นทางไปยังฟังก์ชั่นอื่น ๆ เช่นอีเมลหรือคัดลอกไปยังไฟล์เป็นการแสดงเนื้อหาแคช


29

คุณมีมันย้อนหลัง ob_start ไม่ได้บัฟเฟอร์ส่วนหัวมันบัฟเฟอร์เนื้อหา การใช้ob_startช่วยให้คุณเก็บเนื้อหาไว้ในบัฟเฟอร์ฝั่งเซิร์ฟเวอร์จนกว่าคุณจะพร้อมที่จะแสดง

โดยทั่วไปจะใช้เพื่อให้หน้าสามารถส่งส่วนหัว 'หลังจาก' พวกเขา 'ส่ง' เนื้อหาบางส่วนไปแล้ว (เช่นการเปลี่ยนเส้นทางครึ่งทางผ่านการแสดงผลหน้า)


3
+1 ฉันก็สับสนกับการใช้งานจริงของฟังก์ชั่น คำตอบของคุณเกี่ยวกับการใช้งานในช่วง "การเปลี่ยนเส้นทาง" ทำให้ฉันนึกถึงทุกครั้งที่ฉันพบข้อผิดพลาด "ส่วนหัวที่ส่งไปแล้ว" ขอบคุณ
pat

13

ฉันชอบ:

ob_start();
echo("Hello there!");
$output = ob_get_clean(); //Get current buffer contents and delete current output buffer

8

นี่คือชี้แจงเพิ่มเติมคำตอบ JD Isaaks ...

ปัญหาที่คุณพบบ่อยคือคุณกำลังใช้ php เพื่อส่งออก html จากแหล่ง php ที่แตกต่างกันและแหล่งเหล่านั้นมักจะด้วยเหตุผลใดก็ตามที่แสดงผลด้วยวิธีต่างๆ

บางครั้งคุณมีเนื้อหา html ตามตัวอักษรที่คุณต้องการส่งออกไปยังเบราว์เซอร์โดยตรง บางครั้งเอาต์พุตกำลังถูกสร้างแบบไดนามิก (ฝั่งเซิร์ฟเวอร์)

เนื้อหาแบบไดนามิกจะเป็นสตริงเสมอ (?) ตอนนี้คุณต้องรวม HTML แบบไดนามิกที่ทำให้เป็นสตริงกับ html ที่ตรงตามตัวอักษร ... เข้ากับโครงสร้างโหนด html ที่มีความหมายเดียว

สิ่งนี้มักจะบังคับให้นักพัฒนาห่อเนื้อหาที่ตรงไปยังแสดงในสตริง (ตามที่ JD Isaak กำลังพูดถึง) เพื่อให้สามารถส่ง / แทรกอย่างถูกต้องพร้อมกับ html แบบไดนามิก ... แม้ว่าคุณจะไม่ได้จริงๆ ต้องการห่อ

แต่ด้วยการใช้ ob _ ## วิธีการคุณสามารถหลีกเลี่ยงปัญหาการพันสายอักขระ เนื้อหาที่แท้จริงคือแทนที่จะส่งออกไปยังบัฟเฟอร์ จากนั้นในขั้นตอนเดียวเนื้อหาทั้งหมดของบัฟเฟอร์ (html ตัวอักษรทั้งหมดของคุณ) จะถูกรวมเข้ากับสตริง dynamic-html ของคุณ

(ตัวอย่างของฉันแสดง html ตามตัวอักษรที่ถูกส่งออกไปยังบัฟเฟอร์ซึ่งจะถูกเพิ่มไปยัง html-string ... ดูที่ตัวอย่าง JD Isaaks เพื่อดูการตัดคำ -html

<?php // parent.php

//---------------------------------
$lvs_html  = "" ;

$lvs_html .= "<div>html</div>" ;
$lvs_html .= gf_component_assembler__without_ob( ) ;
$lvs_html .= "<div>more html</div>" ;

$lvs_html .= "----<br/>" ;

$lvs_html .= "<div>html</div>" ;
$lvs_html .= gf_component_assembler__with_ob( ) ;
$lvs_html .= "<div>more html</div>" ;

echo $lvs_html ;    
//    02 - component contents
//    html
//    01 - component header
//    03 - component footer
//    more html
//    ----
//    html
//    01 - component header
//    02 - component contents
//    03 - component footer
//    more html 

//---------------------------------
function gf_component_assembler__without_ob( ) 
  { 
    $lvs_html  = "<div>01 - component header</div>" ; // <table ><tr>" ;
    include( "component_contents.php" ) ;
    $lvs_html .= "<div>03 - component footer</div>" ; // </tr></table>" ;

    return $lvs_html ;
  } ;

//---------------------------------
function gf_component_assembler__with_ob( ) 
  { 
    $lvs_html  = "<div>01 - component header</div>" ; // <table ><tr>" ;

        ob_start();
        include( "component_contents.php" ) ;
    $lvs_html .= ob_get_clean();

    $lvs_html .= "<div>03 - component footer</div>" ; // </tr></table>" ;

    return $lvs_html ;
  } ;

//---------------------------------
?>

<!-- component_contents.php -->
  <div>
    02 - component contents
  </div>

4

ฟังก์ชั่นนี้ไม่ได้มีไว้สำหรับส่วนหัวเท่านั้น คุณสามารถทำสิ่งที่น่าสนใจมากมายกับสิ่งนี้ ตัวอย่าง: คุณสามารถแบ่งหน้าของคุณออกเป็นส่วน ๆ และใช้หน้านี้:

$someTemplate->selectSection('header');
echo 'This is the header.';

$someTemplate->selectSection('content');
echo 'This is some content.';

คุณสามารถจับภาพเอาท์พุทที่สร้างขึ้นที่นี่และเพิ่มลงในสองสถานที่ที่แตกต่างกันโดยสิ้นเชิงในเค้าโครงของคุณ


ดูเหมือนว่าฉันกำลังมองหา ฉันต้องการแสดงสิ่ง 'ส่วน' (คิดว่าของไฟล์ JS และ CSS) แต่ฉันต้องสามารถเรียกพวกเขาภายในแม่แบบ (ซึ่งได้รับการโหลดช้ากว่าส่วนหัว) ... ดังนั้นถ้าฉันเรียกว่า "$ this- > addcss ( 'specificCSStoThisView');" ฉันต้องการให้แสดงระหว่างแท็ก <head> อย่างไรก็ตามฉันไม่สามารถ google สิ่งนี้ได้ คุณช่วยชี้ฉันในทิศทางที่ถูกต้องได้ไหม? ขอบคุณ!
NoobishPro

2

สิ่งต่อไปนี้ไม่ได้กล่าวถึงในคำตอบที่มีอยู่: การกำหนดค่าขนาดบัฟเฟอร์ HTTP ส่วนหัวและการซ้อน

การกำหนดค่าขนาดบัฟเฟอร์สำหรับ ob_start:

ob_start(null, 4096); // Once the buffer size exceeds 4096 bytes, PHP automatically executes flush, ie. the buffer is emptied and sent out.

โค้ดด้านบนปรับปรุงประสิทธิภาพของเซิร์ฟเวอร์เนื่องจาก PHP จะส่งชิ้นข้อมูลที่ใหญ่ขึ้นเช่น 4KB (ไม่มีการเรียกใช้ ob_start, php จะส่งแต่ละเสียงสะท้อนไปยังเบราว์เซอร์)

หากคุณเริ่มการบัฟเฟอร์โดยไม่มีขนาดชิ้น (เช่น. ob_start ()) จากนั้นหน้าจะถูกส่งหนึ่งครั้งในตอนท้ายของสคริปต์

การบัฟเฟอร์เอาต์พุตไม่มีผลกับส่วนหัว HTTP ซึ่งจะถูกประมวลผลด้วยวิธีที่ต่างกัน อย่างไรก็ตามเนื่องจากการบัฟเฟอร์คุณสามารถส่งส่วนหัวแม้หลังจากที่ส่งออกเพราะมันยังอยู่ในบัฟเฟอร์

ob_start();  // turns on output buffering
$foo->bar();  // all output goes only to buffer
ob_clean();  // delete the contents of the buffer, but remains buffering active
$foo->render(); // output goes to buffer
ob_flush(); // send buffer output
$none = ob_get_contents();  // buffer content is now an empty string
ob_end_clean();  // turn off output buffering

อธิบายอย่างดีที่นี่: https://phpfashion.com/everything-about-output-buffering-in-php


0

ไม่คุณคิดผิด แต่ทิศทางนั้นเหมาะสม;)

บัฟเฟอร์เอาท์พุทบัฟเฟอร์เอาต์พุตของสคริปต์ นั่นคือสิ่งที่เกิดขึ้นหลังจากนั้นechoหรือ printสิ่งที่มีส่วนหัวคือพวกเขาสามารถส่งได้ถ้าพวกเขายังไม่ได้ส่ง แต่ HTTP กล่าวว่าส่วนหัวนั้นเป็นสัญญาณแรกของการส่งสัญญาณ ดังนั้นหากคุณส่งออกบางอย่างเป็นครั้งแรก (ตามคำขอ) ส่วนหัวจะถูกส่งและคุณไม่สามารถตั้งค่าส่วนหัวอื่น ๆ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.