Ouput buffering geeft probleem bij export naar Excel
In werk in een project en daar wordt regelmatig (rapport) data naar Excel geexporteerd. Hiervoor is ooit listxl.php genomen ik geloof van IBM of zo. Dit werkt in zekere mate goed.
Echter er doen zich problemen voor op het moment dat het output buffer bv. nog met scherm meldingen of stukken HTML gevuld staat. Vervolgens kan dan het excel .xml bestand niet meer geopend worden met Excel. Dan treedt de melding "Bestand beschadigd..." op.
En wat ik ook denk nadat de gehele listxl.php is uitgevoerd en ik DENK dat het bestand al is afgesloten/weggeschreven, maar dat is misschien niet correct, want er wordt dan nog wat naar het scherm geschreven en dat zie ik dan ook in het .xml bestand terug zoals <script></script>.
Nadenkend/googlend heb ik dit toegevoegd:
Nu werkt het maar als ik de uitleg lees " Clean (erase) the output buffer and turn off output buffering", dan vooral het laatste denk ik, is dit wel de juiste oplossing?
Ik weet hier niet de consequentie van en daarom eigenlijk de vraag kan ik dit er maar zo ongestraft tussen plaatsen?
Nico
Ook heb ik het vermoeden dat je niet ergens de bufferinhoud opslaat (in een variabele)? Ik zou dus eerder een aanroep van ob_get_clean() verwachten in plaats van ob_end_clean() eigenlijk.
Als je je php applicatie op de juiste manier opbouwt heb je helemaal geen outputbuffering nodig. Dat is voor mij nog altjd de enigste juiste manier.
Frank Nietbelangrijk op 10/11/2017 19:44:48:
Als je je php applicatie op de juiste manier opbouwt heb je helemaal geen outputbuffering nodig. Dat is voor mij nog altjd de enigste juiste manier.
Meh, niet helemaal mee eens. Het kan handig zijn als je bestanden bakt (XML,CSV etc., eventueel met behulp van templates) waarbij je output buffering gebruikt. Ook kan het de leesbaarheid van je applicatie vergroten omdat je niet eindeloos hoeft te echo'en / quotes hoeft te escapen als je alles binnen PHP probeert te houden.
Ook kan het helpen bij pagina-opbouw, waarbij een stuk functionaliteit op een bepaalde plek in je HTML-document wordt gezet, zoals JavaScript-snippets die je in een footer toevoegt. Bijvoorbeeld:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<?php
ob_start();
?><script type="text/javascript">
//<![CDATA[
$().ready(function() {
// ... etc ...
}); // ready
//]]>
</script><?php
$this->addInlineJs(ob_get_clean());
?>
ob_start();
?><script type="text/javascript">
//<![CDATA[
$().ready(function() {
// ... etc ...
}); // ready
//]]>
</script><?php
$this->addInlineJs(ob_get_clean());
?>
Lijkt mij een stuk beter leesbaar dan alles echo'en.
EDIT: en dat is dus ook een voorbeeld waarin je dingen niet direct in de goede volgorde kunt zetten, output buffering kan dan uitkomst bieden.
Gewijzigd op 10/11/2017 23:52:59 door Thomas van den Heuvel
Het spijt me Thomas maar ik zou echt niet weten wat ik niet in de goede volgorde kan zetten voor de output. ? !
Toevoeging op 11/11/2017 01:19:48:
p.s. Ik doe ook aan output buffering maar dat heet dan nog variabelen. Met variabelen ben ik nog "in control" maar als de zooi in een output buffer staat dan wordt het wel een heel stukje minder.
Frank Nietbelangrijk op 11/11/2017 01:16:35:
Het spijt me Thomas maar ik zou echt niet weten wat ik niet in de goede volgorde kan zetten voor de output. ? !
Stel dat je een geneste opbouw hebt in pagina-elementen met op het hoogste niveau een "maintemplate". Daarin zitten weer andere stukken functionaliteit, bijvoorbeeld menu's, kleine snippets code en een stuk "hoofdcontent". Dat stuk hoofdcontent wordt éérst "uitgevoerd", omdat die mogelijk aparte javascript- of css-bestanden nodig heeft die in de parent (het maintemplate) ingeladen moet worden. Of dus eerdergenoemde JavaScript snippets die je het liefst net voor de </body> tag wilt zetten (buiten enig ander element). Alle output van dat stuk hoofdcontent wordt in een buffer opgevangen, om vervolgens als de pagina uitgedraaid wordt op de goede plek gezet te worden in het maintemplate.
Dit kun je dus niet lineair doen vanwege de geneste/recursieve opbouw van de content. Elementen uit een lager gelegen niveau bepalen mede het uiterlijk van elementen in een hoger gelegen niveau. Dit zijn in wezen een soort van callbacks.
Het gaat dus verder dan de "variabelen" waar jij het over hebt in die zin dat -om jouw voorbeeld te volgen- het uitvoeren van variabele X van invloed is op de samenstelling van variabele Y.
EDIT: daarnaast buffert PHP van zichzelf al van alles. Dit gebeurt via allerlei interne lagen. Alleen al om die reden zou je, bijvoorbeeld vanuit performanceoverwegingen, output buffering kunnen gebruiken omdat die communicatie dan komt te vervallen / wordt uitgesteld. Tevens kun je met ob_start() een callback-functie definiëren. Een veelgebruikte is ob_gzhandler() die de output tevens comprimeert. Wellicht tegenwoordig een minder belangrijke overweging, maar dit scheelt (op den duur een hoop) bandbreedte.
Gewijzigd op 11/11/2017 15:43:53 door Thomas van den Heuvel