Яке використання ob_start () у php?


298

Є чи ob_start()використовувати для output bufferingтак, щоб заголовки в буфер і не передаються в браузер? Я тут має сенс? Якщо ні, то навіщо нам користуватися 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();Це правильно? Що станеться, якщо це не ввімкнено?
Кевін Вілер

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] ....

  6. Захоплення виводу в буфер означає, що він може бути перенаправлений на інші функції, такі як електронна пошта, або скопійований у файл у вигляді кешованого зображення вмісту


29

У вас це є назад. ob_start не буферизує заголовки, він буферизує вміст. Використання ob_startдозволяє зберігати вміст у буфері на стороні сервера, поки ви не будете готові до його відображення.

Зазвичай це використовується для того, що сторінки можуть надсилати заголовки після того, як вони вже "надіслали" деякий вміст (тобто, прийнявши рішення про переадресацію наполовину через візуалізацію сторінки).


3
+1 Я теж був розгублений щодо фактичного використання функції. Ваша відповідь щодо його використання під час "перенаправлення" нагадувала мені про всі часи, що у мене була помилка "Заголовки вже надіслані". Спасибі
пт

13

Я віддаю перевагу:

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

8

це для подальшого уточнення відповіді Дж. Д. Ісаака ...

Проблема, з якою ви стикаєтеся часто, полягає в тому, що ви використовуєте php для виведення html з багатьох різних джерел php, і ці джерела часто з будь-якої причини виводяться різними способами.

Іноді у вас є буквальний html-вміст, який ви хочете безпосередньо вивести у браузер; в іншому випадку результат динамічно створюється (на сервері).

Динамічний контент завжди (?) Буде рядком. Тепер ви повинні поєднати цей складний динамічний HTML з будь-яким буквальним, прямим для відображення html ... в одну значиму структуру вузла html.

Зазвичай це змушує розробника загортати весь цей вміст прямого відображення у рядок (як обговорював JD Isaak), щоб він міг бути належним чином доставлений / вставлений у поєднанні з динамічним html ... навіть якщо ви насправді не справді хочу, щоб його загорнули.

Але за допомогою методів ob _ ## ви можете уникнути цього заплутаного рядка. Замість цього буквальний вміст виводиться в буфер. Тоді за один простий крок весь вміст буфера (весь ваш буквальний html) об'єднується у ваш рядок динамичного HTML.

(Мій приклад показує, що в буфер виводиться буквальний html, який потім додається до HTML-рядку ... подивіться також на приклад 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>. Я, здається, не можу це гугл. Не могли б ви вказати мене в правильному напрямку? Дякую!
NoobishPro

2

Наступні речі не згадуються в існуючих відповідях: Конфігурація розміру буфера HTTP Header та Nesting.

Конфігурація розміру буфера для 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 надсилатиме більші шматки даних, наприклад, 4 КБ (без виклику 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 каже, що заголовки - це найперша передача. Тож якщо ви виводите щось уперше (у запиті), заголовки надсилаються, і ви не можете встановити жодні інші заголовки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.