Việc sử dụng ob_start () trong php là gì?


298

Được ob_start()sử dụng để output bufferingcác tiêu đề được đệm và không được gửi đến trình duyệt? Tôi có ý nghĩa ở đây? Nếu không thì tại sao chúng ta nên sử dụng ob_start()?

Câu trả lời:


481

Hãy nghĩ về ob_start()câu nói "Bắt đầu nhớ mọi thứ thường sẽ được xuất ra, nhưng chưa hoàn toàn làm gì với nó."

Ví dụ:

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

Có hai chức năng khác mà bạn thường ghép nối nó với: ob_get_contents(), mà về cơ bản cung cấp cho bạn bất cứ điều gì đã được "cứu" vào đệm vì nó đã được bật với ob_start(), và sau đó ob_end_clean()hoặc ob_flush(), mà một trong hai dừng việc tiết kiệm và loại bỏ bất cứ điều gì đã được cứu, hoặc dừng lại tiết kiệm và đầu ra tất cả cùng một lúc, tương ứng.


55
Giải thích tuyệt vời. Tôi sẽ tiến thêm một bước và thay thế ob_get_contents()bằng ob_get_clean()và loại bỏ ob_end_clean()ob_get_clean()về cơ bản thực hiện cả hai chức năng. Tham khảo: php.net/manual/en/feft.ob-get-clean.php (PHP 4> = 4.3.0, PHP 5)
Con Antonakos

Tôi giả sử bộ đệm đầu ra phải được kích hoạt theo thứ tự tệp .ini để gọi ob_start();Có đúng không? Điều gì xảy ra nếu nó không được kích hoạt?
Kevin Wheeler

5
@Riley Dutton Bạn không nói rằng tại sao ob_start () được sử dụng
Vishnu R Nair

Có cùng một vấn đề, sau khi sửa mã của tôi với ob_end_cleannó hoạt động như một bùa mê! Cảm ơn @Riley Dutton
Martins

160

Tôi sử dụng điều này để tôi có thể thoát ra khỏi PHP với rất nhiều HTML nhưng không kết xuất được. Nó tiết kiệm cho tôi khỏi việc lưu trữ nó dưới dạng một chuỗi vô hiệu hóa mã màu IDE.

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

Thay vì:

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

1
Điều này có thể được sử dụng như một cách để có nhiều trang html trong một PHP và gọi chúng thông qua GET không?
joshkrz

1
Tôi cho là như vậy nhưng nó không có vẻ là một ý tưởng tốt. Sẽ tốt hơn để tải chúng từ các mẫu riêng biệt.
JD Isaacks

1
Lưu ý rằng kỹ thuật này sử dụng ob_get_clean(), không phải ob_end_clean()
Blazemonger

11
Không bao giờ nghĩ về điều này, đó là một cách cực kỳ thân thiện với IDE để phát triển! Thêm vào đó, nó loại bỏ nhu cầu của tôi để có Javascript hoặc HTML dưới dạng một chuỗi trong PHP của tôi, liên tục thoát \ ", điều này gây khó chịu
J-Dizzle

1
Hình ảnh của bạn cho một bức tranh rõ ràng về lợi ích của việc sử dụng ob_start.
klewis

86

Câu trả lời được chấp nhận ở đây mô tả những gì ob_start()không - không phải tại sao nó được sử dụng (đó là câu hỏi được hỏi).

Như đã nêu ở nơi khác ob_start()tạo ra một bộ đệm mà đầu ra được ghi vào.

Nhưng không ai đề cập rằng có thể xếp chồng nhiều bộ đệm trong PHP. Xem ob_get_level ().

Vì sao ....

  1. Gửi HTML tới trình duyệt trong các phần lớn hơn mang lại lợi ích hiệu suất từ ​​việc giảm chi phí mạng.

  2. Truyền dữ liệu ra khỏi PHP trong các khối lớn hơn mang lại lợi ích về hiệu năng và năng lực bằng cách giảm số lượng chuyển đổi ngữ cảnh cần thiết

  3. Truyền các khối dữ liệu lớn hơn cho mod_gzip / mod_deflate mang lại lợi ích hiệu suất trong đó việc nén có thể hiệu quả hơn.

  4. đệm đầu ra có nghĩa là bạn vẫn có thể thao tác các tiêu đề HTTP sau này trong mã

  5. một cách rõ ràng đỏ bừng bộ đệm sau khi xuất ra [đầu] .... [/ head] có thể cho phép trình duyệt để bắt đầu marshaling các nguồn lực khác cho các trang trước khi Hoàn thành dòng HTML.

  6. Nắm bắt đầu ra trong bộ đệm có nghĩa là nó có thể được chuyển hướng đến các chức năng khác như email hoặc được sao chép vào một tệp dưới dạng đại diện được lưu trong bộ nhớ cache của nội dung


29

Bạn có nó ngược. ob_start không đệm các tiêu đề, nó đệm nội dung. Việc sử dụng ob_startcho phép bạn giữ nội dung trong bộ đệm phía máy chủ cho đến khi bạn sẵn sàng hiển thị nội dung đó.

Điều này thường được sử dụng để các trang có thể gửi tiêu đề 'sau khi' chúng đã 'gửi' một số nội dung (nghĩa là quyết định chuyển hướng một nửa thông qua kết xuất trang).


3
+1 Tôi cũng bối rối khi sử dụng chức năng thực tế. Câu trả lời của bạn về việc sử dụng nó trong "chuyển hướng" nhắc nhở tôi về tất cả những lần tôi gặp lỗi "Tiêu đề đã được gửi". Cảm ơn
vỗ

13

Tôi thích:

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

8

điều này là để làm rõ hơn câu trả lời của JD Isaaks ...

Vấn đề bạn gặp phải thường xuyên là bạn đang sử dụng php để xuất html từ nhiều nguồn php khác nhau và những nguồn đó thường, vì bất kỳ lý do gì, xuất ra thông qua các cách khác nhau.

Đôi khi bạn có nội dung html theo nghĩa đen mà bạn muốn trực tiếp xuất ra trình duyệt; lần khác, đầu ra đang được tạo động (phía máy chủ).

Nội dung động luôn luôn là (?) Sẽ là một chuỗi. Bây giờ bạn phải kết hợp html động được xâu chuỗi này với bất kỳ html nào, trực tiếp để hiển thị ... thành một cấu trúc nút html có ý nghĩa.

Điều này thường buộc nhà phát triển phải bọc tất cả nội dung hiển thị trực tiếp đó thành một chuỗi (như JD Isaak đang thảo luận) để có thể phân phối / chèn chính xác kết hợp với html động ... mặc dù bạn không thực sự muốn nó được bọc

Nhưng bằng cách sử dụng các phương thức ob _ ##, bạn có thể tránh được mớ hỗn độn đó. Thay vào đó, nội dung theo nghĩa đen là đầu ra cho bộ đệm. Sau đó, trong một bước dễ dàng, toàn bộ nội dung của bộ đệm (tất cả html theo nghĩa đen của bạn), được nối vào chuỗi html động của bạn.

(Ví dụ của tôi cho thấy html theo nghĩa đen được xuất ra bộ đệm, sau đó được thêm vào chuỗi html ... cũng xem ví dụ về JD Isaaks để xem chuỗi-gói-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

Chức năng này không chỉ dành cho tiêu đề. Bạn có thể làm rất nhiều thứ thú vị với điều này. Ví dụ: Bạn có thể chia trang của mình thành các phần và sử dụng nó như thế này:

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

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

Bạn có thể nắm bắt đầu ra được tạo ở đây và thêm nó ở hai nơi hoàn toàn khác nhau trong bố cục của bạn.


Loại này trông giống như những gì tôi đang tìm kiếm. Tôi cần kết xuất nội dung thành 'phần' (nghĩ về các tệp JS và CSS), nhưng tôi cần có thể gọi chúng trong mẫu (được tải muộn hơn tiêu đề) ... Vì vậy, nếu tôi gọi "$ this- > addcss ('Cụ thể CSSto ThisView'); " Tôi muốn nó hiển thị giữa các thẻ <head>. Tôi dường như không thể google điều này, tuy nhiên. Bạn có thể chỉ cho tôi đi đúng hướng? Cảm ơn bạn!
NoobishPro

2

Những điều sau đây không được đề cập trong các câu trả lời hiện có: Cấu hình kích thước bộ đệm HTTP Header và Nesting.

Cấu hình kích thước bộ đệm cho 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.

Đoạn mã trên cải thiện hiệu suất máy chủ vì PHP sẽ gửi các khối dữ liệu lớn hơn, ví dụ: 4KB (cuộc gọi obhst ob_start, php sẽ gửi từng tiếng vang tới trình duyệt).

Nếu bạn bắt đầu đệm mà không có kích thước khối (ví dụ: ob_start ()) đơn giản, thì trang sẽ được gửi một lần ở cuối tập lệnh.

Bộ đệm đầu ra không ảnh hưởng đến các tiêu đề HTTP, chúng được xử lý theo cách khác nhau. Tuy nhiên, do bộ đệm, bạn có thể gửi các tiêu đề ngay cả sau khi đầu ra được gửi, bởi vì nó vẫn nằm trong bộ đệm.

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

Giải thích độc đáo tại đây: https : // phpf Fashion.com/everything-about-output-buffering-in-php


0

Không, bạn sai, nhưng hướng phù hợp;)

Bộ đệm đầu ra đệm bộ đệm đầu ra của một tập lệnh. Đó là tất cả mọi thứ sau echohoặc print. Điều với các tiêu đề là, chúng chỉ có thể được gửi, nếu chúng chưa được gửi. Nhưng HTTP nói, các tiêu đề là đầu tiên của truyền. Vì vậy, nếu bạn xuất một cái gì đó lần đầu tiên (trong một yêu cầu), các tiêu đề được gửi và bạn không thể đặt bất kỳ tiêu đề nào khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.