2009-04-06 33 views
5

Tôi có khá một kịch bản khai thác dữ liệu dài, và trong các bộ phận của nó Tôi xin nhắc lại một số thông tin để trang (trong một vòng lặp foreach, trên thực tế.)PHP tiếng vang ngay lập tức

Tuy nhiên tôi nhận thấy rằng những thông tin đang được gửi để duyệt không ngay lập tức như tôi đã hy vọng, nhưng trong 'phân đoạn'.

Có một số chức năng tôi có thể sử dụng sau tiếng vọng của mình để gửi tất cả dữ liệu đến trình duyệt ngay lập tức không?

Cảm ơn.

+0

Tại sao bạn tag này như [tag: dữ liệu khai thác]?!? Câu hỏi không liên quan gì đến việc khai thác dữ liệu, nó chỉ là đệm đầu ra cũ. –

Trả lời

14

Bạn có thể muốn flush(). Tuy nhiên, PHP có thể đang sử dụng bộ đệm đầu ra. Có một vài cách mà điều này có thể thay đổi mọi thứ, nhưng tóm lại, bạn có thể flush(), sau đó ob_flush().

+0

doh, một phút trước tôi. Tốt trên ob_flush() mặc dù, +1 –

+0

@ Jeremy - Tôi đã đưa ra một cuộc bỏ phiếu để bù cho nó :) – Tim

5

Bạn có thể thử sử dụng lệnh flush() sau mỗi lần lặp lại, nhưng ngay cả điều đó cũng không đảm bảo ghi cho máy khách tùy thuộc vào máy chủ web bạn đang chạy.

3

Bạn sẽ có thể sử dụng một cái gì đó như thế này để buộc đầu ra được gửi đi một cách bất ngờ. Đặt nó vào một phần của mã bạn muốn đầu ra được gửi đi.

flush(); 
ob_flush(); 
+0

cần phải là 'ob_flush();' sau đó 'flush();' làm bất cứ điều gì nếu đầu ra đệm là trên. – Kenaniah

4

Cũng lưu ý rằng một số trình duyệt sẽ không bắt đầu hiển thị bất cứ điều gì cho đến khi cơ thể của phản ứng có chứa một lượng dữ liệu nhất định - như 256 hoặc 1024 byte. Tôi đã thấy các ứng dụng trước dữ liệu pad đó với một chú thích dài 1024 ký tự ở gần đầu trang, trước khi chúng hoạt động. Đó là một chút của một hack, nhưng cần thiết.

Điều này áp dụng cho Internet Explorer và Safari IIRC.

Vì vậy,

  • Nếu nó là tuôn ra đầu tiên, hãy chắc chắn rằng bạn có đầu ra ít nhất là 1024 byte sofar (không bao gồm tiêu đề HTTP).
  • Gọi flush()
  • Nếu bạn có thể xác định rằng có đầu ra đệm tại chỗ, vấn đề ob_flush()

Tôi muốn chỉ cần sử dụng

while (ob_get_level()) ob_end_flush(); 

gần đầu của kịch bản của tôi ở đâu đó, và sau đó chỉ cần

flush(); 

bất cứ khi nào tôi muốn xả. Điều này giả định rằng bạn không muốn bất kỳ bộ đệm đầu ra nào cả, ngay cả khi nó được thiết lập trước kịch bản của bạn (chẳng hạn như trong một cấu hình PHP.ini hoặc htaccess).

+1

hoạt động này, và thay vì flush() sau mỗi echo, bạn có thể thực hiện một 'ob_implicit_flush (true);' ngay từ đầu, điều này sẽ dẫn đến hoạt động tuôn ra sau mỗi cuộc gọi đầu ra, để các lời gọi rõ ràng để flush() sẽ không còn cần thiết nữa. – GDmac

+0

Chắc chắn hoạt động! Tôi đã có một kịch bản lệnh xóa hoàn toàn hoạt động tốt trong Explorer, nhưng không phải trong Chrome và Firefox, vì vậy tôi đã tìm ra vấn đề không phải là phía máy chủ. Đệm đầu ra đến ít nhất 1024 byte sau khi gọi ob_implicit_flush (true) đã khiến tất cả trình duyệt cây hiển thị dữ liệu ngay khi nó được gửi đi, mà không cần phải gọi flush() sau trong vòng lặp. Vì vậy, tôi xác nhận ob_implicit_flush (đúng) và đệm 1K là tất cả những gì bạn cần! Làm tốt lắm! –

1

Để hoạt động hoàn hảo này ra trong Google chrome, thử điều này:

$i = 0; 
$padstr = str_pad("",512," "); 
echo $padstr; 

while ($i <= 4){ 
    $padstr = str_pad("",512," "); 
    echo $padstr; 
    echo "boysmakesh <BR> "; 
    flush(); 
    sleep(2); 
    $i = $i + 1; 
} 

Ee đang gửi 512 byte trước khi gửi MỖI tiếng vang. Đừng quên đặt <BR> vào cuối nội dung trước khi bạn xả. Khác nó sẽ không hoạt động trong Chrome nhưng hoạt động trong IE.

Dữ liệu chúng tôi đệm phụ thuộc vào trình duyệt. Đối với một số trình duyệt, nó đủ để có 256 byte nhưng một số cần 1024 byte. Đối với chrome, đó là 512.

1

Phew! Cuối cùng tôi đã tìm thấy câu trả lời cho vấn đề bộ đệm của Google Chrome!Nhờ boysmakesh để đẩy đúng hướng. Dưới đây là các chức năng tôi sử dụng:

function buffer_flush(){ 

    echo str_pad('', 512); 
    echo '<!-- -->'; 

    if(ob_get_length()){ 

     @ob_flush(); 
     @flush(); 
     @ob_end_flush(); 

    } 

    @ob_start(); 

} 

Và đây là cách tôi gọi nó là:

show_view('global', 'header'); // Echos the <html><head>... tags and 
           // includes JS and CSS. 

show_view('global', 'splash_screen'); // Shows a loading image telling 
             // the user that everything's okay. 

buffer_flush(); // Pretty obvious. At this point the loading view shows 
       // up on every browser i've tested (chrome, firefox, 
       // IE 7 & 8) 

show_view('global', 'main'); // Has a loop that echos "Test $i<br>" 5 
          // times and calls buffer_flush() each time. 

show_view('global', 'footer'); // End the html page and use JQuery to 
           // fade out the loading view. 
0
ignore_user_abort(TRUE); // run script in background 
set_time_limit(0); // run script forever 
$interval=150000; 
$i = 0; 

if(
    strpos($_SERVER["HTTP_USER_AGENT"], "Gecko") or 
    strpos($_SERVER["HTTP_USER_AGENT"], "WebKit") 
){ 
    # important to change browser into quirks mode 
    echo '<?xml version="1.0" encoding="iso-8859-1"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'; 
} 

function buffer_flush(){ 
    echo "\n\n<!-- Deal with browser-related buffering by sending some incompressible strings -->\n\n"; 
    for ($i = 0; $i < 5; $i++) 
     echo "<!-- abcdefghijklmnopqrstuvwxyz1234567890aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz11223344556677889900abacbcbdcdcededfefegfgfhghgihihjijikjkjlklkmlmlnmnmononpopoqpqprqrqsrsrtstsubcbcdcdedefefgfabcadefbghicjkldmnoepqrfstugvwxhyz1i234j567k890laabmbccnddeoeffpgghqhiirjjksklltmmnunoovppqwqrrxsstytuuzvvw0wxx1yyz2z113223434455666777889890091abc2def3ghi4jkl5mno6pqr7stu8vwx9yz11aab2bcc3dd4ee5ff6gg7hh8ii9j0jk1kl2lmm3nnoo4p5pq6qrr7ss8tt9uuvv0wwx1x2yyzz13aba4cbcb5dcdc6dedfef8egf9gfh0ghg1ihi2hji3jik4jkj5lkl6kml7mln8mnm9ono -->\n\n"; 

    while (ob_get_level()) 
     ob_end_flush(); 

    if(ob_get_length()){ 
     @ob_flush(); 
     @flush(); 
     @ob_end_flush(); 
    } 
    @ob_start(); 
} 

ob_start(); 

do{ 

    if($i<10){ 
    buffer_flush(); 
    echo ". ";  
    buffer_flush(); 
    usleep($interval); 

    } else { 
    echo sprintf("<pre>%s</pre>", print_r($_SERVER,true)); 
    break; 
    } 

    $i++; 

}while(true); 
5

Vâng, đệm đầu ra của bạn 1024 byte sẽ gây ra hầu hết các trình duyệt để bắt đầu hiển thị nội dung.

Nhưng chúng tôi cũng tìm hiểu từ câu trả lời @ nobody cho câu hỏi "How to flush output after each `echo` call?" rằng hiệu ứng đệm trình duyệt 1024 byte chỉ xảy ra khi trình duyệt phải đoán mã hóa ký tự của trang, có thể được ngăn chặn bằng cách gửi Loại nội dung phù hợp tiêu đề (ví dụ: "Content-Type: text/html; charset = utf-8") hoặc bằng cách chỉ định bộ ký tự nội dung thông qua các thẻ meta html thích hợp. Và nó cũng hiệu quả với tôi trong mọi trình duyệt.

Vì vậy, về cơ bản, tất cả người ta cần phải làm là:

header('Content-Type: text/html; charset=utf-8'); 
ob_implicit_flush(true); 

Với Không có yêu cầu cho padding thêm hoặc đỏ bừng, đó là lợi ích mỹ phẩm tuyệt vời cho các mã! Tất nhiên, tiêu đề phải được gửi trước bất kỳ nội dung nào và một phần cũng phải đảm bảo không có bộ đệm đầu ra nào đang diễn ra.

Vấn đề chắc chắn đã được giải quyết cho tôi! Xin vui lòng (+1) @ không ai trả lời về câu hỏi khác cũng như nếu nó làm việc cho bạn. Nếu, mặc dù, một trong những vẫn gặp vấn đề, tôi đề nghị kiểm tra các câu trả lời cho câu hỏi khác cho các tình huống cụ thể khác mà có thể ngăn chặn xả ngầm tiềm ẩn hoạt động chính xác.

+0

Lưu ý: Nếu một người muốn kiểm soát thời điểm các khối dữ liệu được gửi đến máy khách, thì người dùng chỉ cần sử dụng lệnh flush() tại thời điểm mong muốn thay vì dựa vào ob_implicit_flush (true). –

+0

ồ tuyệt vời. tôi đã thử nghiệm với cùng một vấn đề và chỉ cần thử với một loại nội dung và nó đã làm việc ... và đã trả lời câu hỏi của riêng tôi với cùng một vấn đề nhưng đối với xmlhttprequest ... có nó hoạt động. và khi tôi tìm kiếm cho cùng tôi tìm thấy câu trả lời của bạn. –

0

Chạy php 5.5 trên IIS 7, IE 11 (máy chủ giành chiến thắng) Tôi thấy điều này đã hoạt động như các dòng mở của tệp. Lưu ý đặt câu lệnh while trước khi tiêu đề gây ra lỗi tiêu đề đã được viết.

header('Content-Type: text/html; charset=utf-8'); 
while (ob_get_level()) ob_end_flush(); 
ob_implicit_flush(true); 

Tham chiếu thêm vào ob_flush() trong tập lệnh khiến bộ đệm không tồn tại lỗi.

Điều này làm việc tốt khi tôi đang xử lý tệp và gửi báo cáo sql cho trình duyệt, tuy nhiên khi tôi kết nối db (ms server 2008), tôi không có đầu vào nào được trả lại cho đến khi tập lệnh hoàn tất.

0

sự kết hợp này cuối cùng làm việc cho tôi, dựa trên câu trả lời của thomasrutter

while (ob_get_level()) ob_end_flush(); 
ob_implicit_flush(true); 
Các vấn đề liên quan