php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #45391 Can not set chunk size to 1 with ob_start()
Submitted: 2008-06-29 13:09 UTC Modified: 2021-07-07 14:53 UTC
From: sv4php at fmethod dot com Assigned: cmb (profile)
Status: Wont fix Package: Output Control
PHP Version: 5.2.6 OS: *
Private report: No CVE-ID: None
 [2008-06-29 13:09 UTC] sv4php at fmethod dot com
Description:
------------
chunk_size in ob_start() has no way to be specified to "1 byte" because 1 was aliased to 4096.

I understand this was done since it was deemed there's no use case for calling the handler immediately after echo, but there is.

I need my handler to receive every item being outputted exactly after it was outputted exactly as it is, i.e. no buffering.

This is very useful for "deferred dynamic composition", for example batch "string id" replace in international apps, without manually searching for "macros" with str_replace or regular expression (cleaner and more secure). 

Example below of this technique (I use chunk_size = 2, to demonstrate, but if the string id-s are one symbol apart, it'll break my example as I can't specify 1 byte in chunk_size, which is the gut of the problem.)

I suggest one of two solutions:

- Make "1" be "1", and leave the default value (which most people use) as 4096 bytes.

- To preserve full BC, leave "1" to be "4096" but add a new alias, "-1" to mean "no buffering" (i.e. 1 byte chunk_size). Ugly, but BC.


Reproduce code:
---------------
<?php
// stores all parts of the output, static via the handler, dynamic via translateStringId()
$composition = array(); 

function handler($input) {
	global $composition;
	 $composition[] = $input;
	return ''; // discard output (just saves a bit of RAM)
}


function echoStringId($stringId) 
{
	global $composition;
	$composition[] = array($stringId); // we chose array wrapped string to mean "string id to be resolved later";
}

function batchReplaceStringIds() {
	global $composition;
	
	// a mock of a SELECT query that would fetch all string ids at once (much faster than one query per string).
	$mockQuery = array(
		'stringid1' => 'Foo', 
		'stringid2' => 'Bar',
	);
	
	foreach ($composition as & $compositionItem) {
		if (is_array($compositionItem)) {
			$compositionItem = $mockQuery[$compositionItem[0]];
		}
	}
}

// THE PAGE BEGINS:

ob_start('handler', 2);
?>

This is string one: <? echoStringId('stringid1'); ?>. And, this is string two: <? echoStringId('stringid2'); ?>.

<?
ob_end_clean();

// PAGE ENDS. PROCESSING AND OUTPUT:

batchReplaceStringIds();

// echo the computed output, outputs: This is string one: Foo. And, this is string two: Bar.
foreach ($composition as $compositionItem) echo $compositionItem;
?>

Expected result:
----------------
Expected: being able to use handlers without buffering.

Actual result:
--------------
Actual: unable to turn off buffering.

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-12-31 00:22 UTC] cmb@php.net
-Package: Feature/Change Request +Package: Output Control
 [2021-07-07 14:53 UTC] cmb@php.net
-Status: Open +Status: Wont fix -Assigned To: +Assigned To: cmb
 [2021-07-07 14:53 UTC] cmb@php.net
That looks like as terrible use case to me, and given there have
been no comments for more than ten years, I'm closing as WONTFIX.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Dec 26 15:01:32 2024 UTC