php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76571 str_replace fails to replace string in special output buffered environment
Submitted: 2018-07-03 07:22 UTC Modified: 2018-07-03 09:12 UTC
From: roland at nextendweb dot com Assigned:
Status: Not a bug Package: Output Control
PHP Version: 7.2.7 OS:
Private report: No CVE-ID: None
 [2018-07-03 07:22 UTC] roland at nextendweb dot com
Description:
------------
http://sandbox.onlinephpfunctions.com/code/08eee50202cb2e8ce5b6e849aacb7c5bf37de4ba

Test script:
---------------
<?php
class a {

    private static $bug = 'World';

    public static function parse_output($buffer) {

        $buffer = str_replace('there', self::$bug, $buffer);

        self::$bug = 'What?';

        return $buffer;
    }
}

ob_start('a::parse_output');
echo "Hello there";

$content = ob_get_contents();
ob_clean();

echo $content;
ob_end_flush();

Expected result:
----------------
Hello World

Actual result:
--------------
Hello What?

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-07-03 08:41 UTC] requinix@php.net
-Status: Open +Status: Not a bug
 [2018-07-03 08:41 UTC] requinix@php.net
http://php.net/manual/en/function.ob-start.php
> The [output_callback] function will be called when the output buffer is flushed (sent) or cleaned (with
> ob_flush(), ob_clean() or similar function) or when the output buffer is flushed to the browser at the end of the
> request.

1. When you echo "Hello there", the callback is *not invoked immediately*
2. ob_get_contents returns "Hello there" back
3. ob_clean sends "Hello there" to the callback, which replaces using "World", but the result is discarded
4. You echo the original "Hello there" again
5. ob_end_flush sends the new "Hello there" to the callback, which replaces using "What?", and the result is sent

Is there a reasonable use case behind this problem? Because otherwise what you should be doing is simply
  ob_start('a::parse_output');
  echo "Hello there";
  ob_end_flush();
 [2018-07-03 09:05 UTC] roland at nextendweb dot com
Well, it makes sense. So I should use the output callback phase parameter to check.
Could you tell me which is the phase which runs only once when the output buffer closed completely?

class a {

    private static $bug = 'World';
    

    public static function parse_output($buffer, $phase) {

        if ( $phase & PHP_OUTPUT_HANDLER_FINAL ){

            $buffer = str_replace('there', self::$bug, $buffer);
    
            self::$bug = 'What?';
        }

        return $buffer;
    }
}
 [2018-07-03 09:12 UTC] requinix@php.net
FINAL is the one.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Mar 29 01:01:28 2024 UTC