Apa gunanya ob_start () di php?


298

Apakah ob_start()digunakan output bufferingagar tajuk buffer dan tidak dikirim ke browser? Apakah saya masuk akal di sini? Jika tidak maka mengapa kita harus menggunakan ob_start()?

Jawaban:


481

Anggap ob_start()sebagai pepatah, "Mulailah mengingat semua yang biasanya dihasilkan, tetapi jangan lakukan apa-apa dengan itu."

Sebagai contoh:

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

Ada dua fungsi lain yang biasanya Anda pasangkan dengan ob_get_contents():, yang pada dasarnya memberi Anda apa pun yang telah "disimpan" ke buffer sejak dinyalakan ob_start(), dan kemudian ob_end_clean()atau ob_flush(), yang menghentikan penyimpanan dan membuang apa pun yang disimpan, atau berhenti menyimpan dan output semuanya sekaligus, masing-masing.


55
Penjelasan yang bagus. Saya akan melangkah lebih jauh dan mengganti ob_get_contents()dengan ob_get_clean()dan menghapus ob_end_clean()karena ob_get_clean()pada dasarnya melakukan kedua fungsi. Referensi: php.net/manual/en/function.ob-get-clean.php (PHP 4> = 4.3.0, PHP 5)
Con Antonakos

Saya berasumsi buffering output harus diaktifkan dalam perintah file .ini untuk memanggil ob_start();Apakah ini benar? Apa yang terjadi jika tidak diaktifkan?
Kevin Wheeler

5
@Riley Dutton Anda tidak memberi tahu mengapa ob_start () digunakan
Vishnu R Nair

Punya masalah yang sama, setelah memperbaiki kode saya dengan ob_end_cleanitu berfungsi seperti pesona! Terima kasih @Riley Dutton
Martins

160

Saya menggunakan ini sehingga saya bisa keluar dari PHP dengan banyak HTML tetapi tidak membuatnya. Ini menyelamatkan saya dari menyimpannya sebagai string yang menonaktifkan pengkodean warna IDE.

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

Dari pada:

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

1
Apakah ini dapat digunakan sebagai cara untuk memiliki beberapa halaman html dalam satu PHP dan memanggil mereka melalui GET?
joshkrz

1
Saya kira begitu tetapi itu tidak terdengar seperti ide yang bagus. Akan lebih baik memuatnya dari templat terpisah.
JD Isaacks

1
Perhatikan bahwa teknik ini menggunakan ob_get_clean(), bukan ob_end_clean()
Blazemonger

11
Tidak pernah memikirkan ini, itu cara yang luar biasa ramah IDE untuk dikembangkan! Plus, itu menghilangkan kebutuhan saya untuk memiliki Javascript atau HTML sebagai string di PHP saya, terus-menerus melarikan diri \ "dll, yang menjengkelkan
J-Dizzle

1
Visual Anda memberikan gambaran yang jelas tentang manfaat menggunakan ob_start.
klewis

86

Jawaban yang diterima di sini menjelaskan apa yang ob_start()dilakukan - bukan mengapa digunakan (yang merupakan pertanyaan yang diajukan).

Seperti yang dinyatakan di tempat lain ob_start()membuat buffer yang outputnya ditulis untuk.

Tetapi tidak ada yang menyebutkan bahwa mungkin untuk menumpuk banyak buffer dalam PHP. Lihat ob_get_level ().

Adapun alasannya ....

  1. Mengirim HTML ke browser dalam potongan yang lebih besar memberikan manfaat kinerja dari pengurangan overhead jaringan.

  2. Mengoper data keluar dari PHP dalam potongan yang lebih besar memberikan manfaat kinerja dan kapasitas dengan mengurangi jumlah sakelar konteks yang diperlukan

  3. Melewatkan potongan data yang lebih besar ke mod_gzip / mod_deflate memberikan manfaat kinerja karena kompresi dapat lebih efisien.

  4. buffering output berarti bahwa Anda masih dapat memanipulasi header HTTP di kemudian hari dalam kode

  5. secara eksplisit membilas buffer setelah mengeluarkan [head] .... [/ head] dapat memungkinkan browser untuk mulai menyusun sumber daya lain untuk halaman sebelum aliran HTML selesai.

  6. Menangkap output dalam buffer berarti dapat diarahkan ke fungsi lain seperti email, atau disalin ke file sebagai representasi konten yang di-cache


29

Anda memilikinya mundur. ob_start tidak buffer header, itu buffer konten. Menggunakan ob_startmemungkinkan Anda untuk menyimpan konten di buffer sisi server sampai Anda siap untuk menampilkannya.

Ini biasanya digunakan untuk sehingga halaman dapat mengirim header 'setelah' mereka telah 'mengirim' beberapa konten (yaitu, memutuskan untuk mengarahkan setengah jalan melalui rendering halaman).


3
+1 Saya juga bingung tentang penggunaan fungsi yang sebenarnya. Jawaban Anda tentang penggunaannya selama "pengalihan" mengingatkan saya pada semua waktu bahwa saya memiliki kesalahan "Header sudah dikirim". Terima kasih
pat

13

Saya lebih memilih:

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

8

ini untuk lebih memperjelas jawaban JD Isaaks ...

Masalah yang sering Anda temui adalah Anda menggunakan php untuk meng-output html dari berbagai sumber php, dan sumber-sumber itu seringkali, untuk alasan apa pun, menghasilkan melalui berbagai cara.

Terkadang Anda memiliki konten html literal yang ingin Anda hasilkan langsung ke browser; lain kali output sedang dibuat secara dinamis (sisi server).

Konten dinamis selalu (?) Akan menjadi string. Sekarang Anda harus menggabungkan html dinamis yang dirangkai ini dengan html literal, langsung-ke-tampilan apa pun ... menjadi satu struktur simpul html yang berarti.

Ini biasanya memaksa pengembang untuk membungkus semua konten yang langsung ditampilkan menjadi string (seperti yang sedang dibahas JD Isaak) sehingga dapat dikirim / dimasukkan dengan benar bersama dengan html dinamis ... meskipun Anda tidak benar-benar ingin dibungkus.

Tetapi dengan menggunakan metode ob _ ## Anda dapat menghindari kekacauan pembungkus string. Konten literal, sebaliknya, output ke buffer. Kemudian dalam satu langkah mudah seluruh isi buffer (semua html literal Anda), disatukan ke string dinamis-html Anda.

(Contoh saya menunjukkan html literal menjadi output ke buffer, yang kemudian ditambahkan ke html-string ... lihat juga contoh JD Isaaks untuk melihat string-wrapping-of-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

Fungsi ini bukan hanya untuk header. Anda dapat melakukan banyak hal menarik dengan ini. Contoh: Anda dapat membagi halaman Anda menjadi beberapa bagian dan menggunakannya seperti ini:

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

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

Anda dapat menangkap output yang dihasilkan di sini dan menambahkannya di dua tempat yang sangat berbeda dalam tata letak Anda.


Jenis ini terlihat seperti apa yang saya cari. Saya perlu membuat hal-hal menjadi 'bagian' (pikirkan file JS dan CSS), tetapi saya harus dapat memanggil mereka di dalam template (yang akan dimuat lebih lambat dari header) ... Jadi jika saya memanggil "$ this- > addcss ('specificCSStoThisView'); " Saya ingin merender di antara tag <head>. Namun saya tidak bisa menggunakan google ini. Bisakah Anda mengarahkan saya ke arah yang benar? Terima kasih!
NoobishPro

2

Hal-hal berikut tidak disebutkan dalam jawaban yang ada: Konfigurasi ukuran penyangga HTTP Header dan Nesting.

Konfigurasi ukuran penyangga untuk 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.

Kode di atas meningkatkan kinerja server karena PHP akan mengirim potongan data yang lebih besar, misalnya, 4KB (tanpa panggilan ob_start, php akan mengirim setiap gema ke browser).

Jika Anda mulai buffering tanpa ukuran chunk (mis. Ob_start sederhana ()), maka halaman tersebut akan dikirim satu kali di akhir skrip.

Output buffering tidak mempengaruhi header HTTP, mereka diproses dengan cara yang berbeda. Namun, karena buffering Anda dapat mengirim header bahkan setelah output dikirim, karena masih dalam buffer.

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

Dijelaskan dengan baik di sini: https://phpfashion.com/everything-about-output-buffering-in-php


0

Tidak, Anda salah, tetapi arahnya cocok;)

Buffer-Output menyangga output skrip. Thats (singkatnya) everthing setelah echoatau print. Masalahnya dengan header adalah, bahwa mereka hanya dapat dikirim, jika mereka belum dikirim. Tetapi HTTP mengatakan, header itu adalah yang pertama dari transmisi. Jadi, jika Anda menampilkan sesuatu untuk pertama kalinya (dalam permintaan) tajuk dikirim dan Anda tidak dapat mengatur tajuk lainnya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.