À quoi sert ob_start () en php?


298

Est ob_start()utilisé pour output bufferingque les en-têtes soient mis en mémoire tampon et ne soient pas envoyés au navigateur? Suis-je logique ici? Sinon, pourquoi devrions-nous l'utiliser ob_start()?

Réponses:


481

Pensez ob_start()à dire "Commencez à vous souvenir de tout ce qui serait normalement sorti, mais ne faites rien pour l'instant."

Par exemple:

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

Il y a deux autres fonctions avec ob_get_contents()lesquelles vous l'associez généralement:, qui vous donne essentiellement ce qui a été "enregistré" dans le tampon depuis qu'il a été activé avec ob_start(), puis ob_end_clean()ou ob_flush(), qui arrête de sauvegarder les choses et rejette tout ce qui a été enregistré, ou arrête de sauvegarder et sort tout cela à la fois, respectivement.


55
Grande explication. Je voudrais aller plus loin et remplacer ob_get_contents()par ob_get_clean()et supprimer ob_end_clean()car ob_get_clean()remplit essentiellement les deux fonctions. Référence: php.net/manual/en/function.ob-get-clean.php (PHP 4> = 4.3.0, PHP 5)
Con Antonakos

Je suppose que la mise en mémoire tampon de sortie doit être activée dans l'ordre du fichier .ini pour appeler ob_start();Est-ce correct? Que se passe-t-il s'il n'est pas activé?
Kevin Wheeler

5
@Riley Dutton Vous ne dites pas pourquoi l'ob_start () est utilisé
Vishnu R Nair

J'ai eu le même problème, après avoir corrigé mon code, ob_end_cleancela fonctionne comme un charme! Merci @Riley Dutton
Martins

160

J'utilise ceci pour pouvoir sortir de PHP avec beaucoup de HTML mais pas le rendre. Cela m'évite de le stocker sous forme de chaîne qui désactive le codage couleur IDE.

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

Au lieu de:

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

1
Cela peut-il être utilisé comme un moyen d'avoir plusieurs pages html dans un PHP et de les appeler via GET?
joshkrz

1
Je suppose que oui, mais cela ne semble pas être une bonne idée. Il serait préférable de les charger à partir de modèles distincts.
JD Isaacks

1
Notez que cette technique utilise ob_get_clean(), pas ob_end_clean()
Blazemonger

11
Je n'y ai jamais pensé, c'est une façon incroyablement conviviale de se développer! De plus, cela supprime le besoin d'avoir Javascript ou HTML comme chaîne dans mon PHP, s'échappant constamment \ "etc., ce qui est ennuyeux
J-Dizzle

1
Votre visuel donne une image claire des avantages de l'utilisation de ob_start.
klewis

86

La réponse acceptée ici décrit ce qui ob_start()ne fonctionne pas - pas pourquoi elle est utilisée (ce qui était la question posée).

Comme indiqué ailleurs, ob_start()crée un tampon dans lequel la sortie est écrite.

Mais personne n'a mentionné qu'il est possible d'empiler plusieurs tampons dans PHP. Voir ob_get_level ().

Quant au pourquoi ...

  1. L'envoi de HTML au navigateur en plus gros morceaux offre un avantage en termes de performances grâce à une surcharge réseau réduite.

  2. La transmission des données de PHP dans des segments plus importants offre un avantage en termes de performances et de capacité en réduisant le nombre de changements de contexte requis

  3. Le passage de gros morceaux de données à mod_gzip / mod_deflate offre un avantage en termes de performances dans la mesure où la compression peut être plus efficace.

  4. la mise en mémoire tampon de la sortie signifie que vous pouvez toujours manipuler les en-têtes HTTP plus tard dans le code

  5. vider explicitement le tampon après la sortie de [head] .... [/ head] peut permettre au navigateur de commencer à marshaler d'autres ressources pour la page avant la fin du flux HTML.

  6. La capture de la sortie dans un tampon signifie qu'elle peut être redirigée vers d'autres fonctions telles que le courrier électronique ou copiée dans un fichier en tant que représentation en cache du contenu


29

Vous l'avez à l'envers. ob_start ne met pas les en-têtes en mémoire tampon, il met en mémoire tampon le contenu. L'utilisation ob_startvous permet de conserver le contenu dans un tampon côté serveur jusqu'à ce que vous soyez prêt à l'afficher.

Ceci est couramment utilisé pour que les pages puissent envoyer des en-têtes après avoir «déjà» envoyé du contenu (c'est-à-dire décider de rediriger à mi-chemin du rendu d'une page).


3
+1 Moi aussi, j'étais confus quant à l'utilisation réelle de la fonction. Votre réponse concernant son utilisation lors de la "redirection" m'a rappelé toutes les fois où j'ai eu l'erreur "En-têtes déjà envoyés". Merci
pat

13

Je préfère:

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

8

c'est pour clarifier davantage la réponse de JD Isaaks ...

Le problème que vous rencontrez souvent est que vous utilisez php pour sortir du HTML à partir de nombreuses sources php différentes, et ces sources sont souvent, pour une raison quelconque, sorties via différentes manières.

Parfois, vous avez du contenu HTML littéral que vous souhaitez afficher directement dans le navigateur; d'autres fois, la sortie est créée dynamiquement (côté serveur).

Le contenu dynamique sera toujours (?) Une chaîne. Vous devez maintenant combiner ce html dynamique stringifié avec n'importe quel html littéral direct à afficher ... dans une structure de nœud html significative.

Cela oblige généralement le développeur à encapsuler tout ce contenu direct à afficher dans une chaîne (comme l'a expliqué JD Isaak) afin qu'il puisse être correctement fourni / inséré en conjonction avec le HTML dynamique ... même si vous ne le faites pas vraiment veulent qu'il soit enveloppé.

Mais en utilisant les méthodes ob _ ##, vous pouvez éviter ce désordre de chaîne. Le contenu littéral est, à la place, sorti dans le tampon. Ensuite, en une seule étape facile, tout le contenu du tampon (tout votre html littéral) est concaténé dans votre chaîne dynamic-html.

(Mon exemple montre que du HTML littéral est sorti dans le tampon, qui est ensuite ajouté à une chaîne html ... regardez également l'exemple JD Isaaks pour voir l'encapsulation de chaîne de 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

Cette fonction n'est pas réservée aux en-têtes. Vous pouvez faire beaucoup de choses intéressantes avec ça. Exemple: vous pouvez diviser votre page en sections et l'utiliser comme ceci:

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

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

Vous pouvez capturer la sortie générée ici et l'ajouter à deux endroits totalement différents de votre mise en page.


Ce genre ressemble à ce que je recherche. J'ai besoin de rendre les choses dans des "sections" (pensez aux fichiers JS et CSS), mais je dois pouvoir les appeler dans le modèle (qui est chargé plus tard que l'en-tête) ... Donc, si j'appelle "$ this- > addcss ('specificCSStoThisView'); " Je veux qu'il s'affiche entre les balises <head>. Cependant, je n'arrive pas à chercher ça sur Google. Pourriez-vous peut-être m'orienter dans la bonne direction? Je vous remercie!
NoobishPro

2

Les éléments suivants ne sont pas mentionnés dans les réponses existantes: Configuration de la taille de la mémoire tampon HTTP Header et Nesting.

Configuration de la taille de la mémoire tampon pour 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.

Le code ci-dessus améliore les performances du serveur car PHP enverra de plus gros morceaux de données, par exemple 4Ko (sans appel ob_start, php enverra chaque écho au navigateur).

Si vous commencez à mettre en mémoire tampon sans la taille du bloc (c'est-à-dire un simple ob_start ()), la page sera envoyée une fois à la fin du script.

La mise en mémoire tampon de sortie n'affecte pas les en-têtes HTTP, ils sont traités de manière différente. Cependant, en raison de la mise en mémoire tampon, vous pouvez envoyer les en-têtes même après l'envoi de la sortie, car elle est toujours dans la mémoire tampon.

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

Bien expliqué ici: https://phpfashion.com/everything-about-output-buffering-in-php


0

Non, vous vous trompez, mais la direction convient;)

L'Output-Buffering met en tampon la sortie d'un script. C'est (en bref) tout après echoou print. Le problème avec les en-têtes est qu'ils ne peuvent être envoyés que s'ils ne sont pas déjà envoyés. Mais HTTP dit que les en-têtes sont les tout premiers de la transmission. Donc, si vous sortez quelque chose pour la première fois (dans une demande), les en-têtes sont envoyés et vous ne pouvez pas définir d'autres en-têtes.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.