Bộ đệm PHP ob_flush () so với flush ()


79

Sự khác biệt giữa ob_flush()flush()và tại sao tôi phải gọi cả hai?

Các ob_flush()tài liệu tham khảo cho biết:

Hàm này sẽ gửi nội dung của bộ đệm đầu ra (nếu có).

Các flush()tài liệu tham khảo cho biết:

Xóa bộ đệm ghi của PHP và bất kỳ phần mềm phụ trợ nào mà PHP đang sử dụng (CGI, máy chủ web, v.v.).

Tuy nhiên, nó tiếp tục nói:

[it] có thể không ghi đè được sơ đồ đệm của máy chủ web của bạn…

Vì vậy, với tôi dường như tôi có thể sử dụng ob_flush()mọi lúc. Tuy nhiên, tôi nhận được kết quả kỳ lạ khi tôi làm điều đó. Ai đó có thể giải thích bằng những thuật ngữ đơn giản những gì đang xảy ra ở đây?

Câu trả lời:


75

ob_flushgửi một bộ đệm do ứng dụng khởi tạo. Có thể có nhiều lồng nhau ob_start()trong bất kỳ tập lệnh PHP nào. ob_flushchuyển nội dung hiện tại lên lớp trên.

Bản thân PHP có thể (theo quyết định của riêng mình) đầu ra bộ đệm. Điều này phụ thuộc vào back-end. Nhưng thường FastCGIcó bộ đệm ổ cắm riêng. Do đó cũng flush()cần phải được gọi để gửi nội dung hiện tại đến máy chủ web.

Và bây giờ máy chủ web có thể tự triển khai một sơ đồ đệm khác ( mod_deflatehoặc bộ lọc nội dung) mà bạn không có ảnh hưởng gì. Nhưng điều này hiếm khi xảy ra, vì nó cần được cấu hình cụ thể.

Dù sao, hãy sử dụng cả hai.


11
Sử dụng ob_flush và tuôn ra và sử dụng chúng theo thứ tự đó.
Robino

17
Chi tiết quan trọng bị thiếu trong câu trả lời này là output_bufferingtùy chọn cấu hình, có giá trị mặc định trong phiên bản sản xuất của php.ini là 4096. Điều đó có nghĩa là khi bất kỳ tập lệnh PHP nào bắt đầu, 4096 byte đầu tiên của đầu ra sẽ được lưu vào bộ đệm (trong bộ đệm có thể tháo rời với ob_flush()). Đây là lý do tại sao nó là cần thiết để sử dụng ob_flush()cũng như flush(). Việc vô hiệu hóa output_bufferingqua php.ini hoặc gọi ob_end_clean()hoặc ob_end_flush()khi bắt đầu tập lệnh sẽ loại bỏ sự cần thiết này.
Mark Amery

Cảm ơn @MarkAmery, nhưng ob_end_clean()ở phần "bắt đầu tập lệnh" có vẻ hơi phản trực quan. Bạn có nghĩa là chúng ta nên bao gồm điều này ngay sau ob_start()và trước khi cả hai tuôn ra?
Khom Nazid

Tôi có một ob_start()và một ob_end_clean()khi bắt đầu kịch bản. Sau đó, sau bất kỳ "tiếng vang" nào trong tập lệnh, tôi cũng bao gồm ob_flush(); flush();và tôi hy vọng rằng trong khi tập lệnh mất thời gian, bất cứ điều gì đã được thực hiện cho đến nay sẽ được xuất trên màn hình (trong trình duyệt). Nhưng không có gì được đưa ra cho đến cuối cùng. Tôi đang thiếu gì?
Khom Nazid,

1
@KhomNazid Quan sát trình duyệt không giống như gỡ lỗi luồng HTTP. Đầu ra gia tăng và bị trì hoãn cho một HTML DOM không hoàn chỉnh có thể không hiển thị. Thực hiện một số kiểm tra CLI với thiết lập hiện tại của bạn. (Và sau đó, và chỉ sau đó, bắt đầu một câu hỏi khác về nó.)
mario

33

ob_flushxóa bộ đệm đầu ra bạn đã tạo bằng một hàm nhưob_start

flush gửi đầu ra có đệm của chính tập lệnh PHP tới trình gọi của nó


25

ob_flush()là xả cấp cao. Nó làm sạch bộ đệm cấp cao và đưa tất cả nội dung vào bộ đệm nội bộ cấp thấp, sẵn sàng gửi.

  • Lưu ý rằng ob_họ các hàm tạo ra các ngăn xếp bộ đệm, vì vậy chỉ cần viết một cách mù quáng ob_flush()ở mọi nơi sẽ thực sự mang lại cho bạn "kết quả kỳ lạ" nếu mã được viết để tận dụng việc xếp chồng này.

flush() là một trình xả cấp thấp, hướng dẫn PHP xả các bộ đệm dữ liệu cấp thấp, nội bộ của nó.

Bên dưới vẫn còn đó, sẽ có bộ đệm lớp ổ cắm; bên dưới đó, có các bộ đệm lớp mạng. Và, ở mức thấp nhất, hàng đợi các electron đi xuống cáp dữ liệu.


Tôi có một ob_start()và một ob_end_clean()khi bắt đầu kịch bản. Sau đó, sau bất kỳ "tiếng vang" nào trong tập lệnh, tôi cũng bao gồm ob_flush(); flush();và tôi hy vọng rằng trong khi tập lệnh mất thời gian, bất cứ điều gì đã được thực hiện cho đến nay sẽ được xuất trên màn hình (trong trình duyệt). Nhưng không có gì được đưa ra cho đến cuối cùng. Tôi đang thiếu gì?
Khom Nazid,

@KhomNazid Buffering bởi các giai đoạn trung gian, giống như máy chủ web, proxy, trình duyệt của bạn ...
Lightness Races ở Orbit

11

Tôi đoán điều này có liên quan đến câu hỏi trước của bạn . Lợi thế đáng kể của việc sử dụng bộ đệm đầu ra là khi nó được sử dụng cùng với nén dữ liệu. Nếu bạn không sử dụng ob_gzhandler, sẽ có rất ít lợi ích. flushmột mình sẽ chỉ cam kết bất kỳ dữ liệu đầu ra nào vẫn còn trên máy chủ. Với ob_startvà các đối tác của nó ob_flush, ob_end_cleanob_end_flush, bất cứ thứ gì đang chờ được nén (xem xét flushob_flushđề cập đến các nhóm khác nhau - obgửi dữ liệu đến flush, flushgửi dữ liệu đến trình duyệt - có thể không chính xác nhưng đó là ý tưởng) sẽ được gói gọn và gửi cho khách hàng .


Cảm ơn, phép loại suy về thùng là một ví dụ hay.
Ben
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.