ID:               33910
 Updated by:       [EMAIL PROTECTED]
 Reported By:      jrweir at gmail dot com
 Status:           Open
 Bug Type:         Output Control
 Operating System: all
 PHP Version:      5.1.0b3
 New Comment:

>Since calling ob_end*() in a destructor has never worked
>nobody has code written expecting it to.

This is obviously not true and you know why: see bug #30578.


Previous Comments:
------------------------------------------------------------------------

[2005-07-28 19:41:39] jrweir at gmail dot com

Currently in 5.1.0b3 the order is
1. call destructors
2. call shutdown functions
3. flush output buffers

I think it should be
1. flush output buffers
2. call destructors
3. call shutdown functions

Reason:
Since calling ob_end*() in a destructor has never worked nobody has
code written expecting it to. However, many people (as in bug #33772)
have code written expecting destructors to run after output buffering.
I'd say there are just as many valid reasons to flush buffers after the
destructors run as there are to flush buffers before they run, but since
it was the latter way since php 5, why change it?

Solution:
Make it illegal to do output buffering in a destructor just as it is in
an output buffering handler.

------------------------------------------------------------------------

[2005-07-28 19:13:47] [EMAIL PROTECTED]

This is a chicken-and-egg problem that can't be solved in an easy way.
Please see bug #33772 for additional details.
If you have any ideas what should be the *right* order of calls -
please tell your opinion. But remember that we have a lot of different
handlers that are called on shutdown. 
See the current order in php-src/main/main.c, php_request_shutdown()
function.

------------------------------------------------------------------------

[2005-07-28 18:59:58] jrweir at gmail dot com

Description:
------------
http://bugs.php.net/bug.php?id=30578
I don't think the way this bug was solved was correct. While I agree
the example code posted above should work as expected, a side effect of
fixing this caused all destructors to run before registered ob handlers.
Destructors used to run after an ob handler, which was very useful for
analyzing script output and setting flags for objects to clean
themselves up appropriately. Consider the following (which is now not
possible in 5.1):

<?php
ob_start('outputHandler');

function outputHandler($buffer){
    // find out if there was a fatal error. If none, allow sql
connections to commit on destruct
    if (!preg_match('/((Fatal|Parse) error: .+ in .+ on line \d+)/',
strip_tags($buffer), $matches)) SQL::setAllowCommit(true);
    return $buffer;
}


class SQL {

    private $connection;
    private static $allowCommit=false;

    public function __construct(){
    }

    public function __destruct(){
        if ($this->connection && self::getAllowCommit()) {
            $this->connection->commit();
            echo ' commit happened ';
        }
        else echo ' no commit happened ';
    }

    public static function getAllowCommit()     { return
self::$allowCommit; }
    public static function setAllowCommit($val) { self::$allowCommit =
$val; }

    public function connectToDatabase($host, $user, $pass, $db){
        $this->connection = new mysqli($host, $user, $pass, $db) or
die('no connection');
        $this->connection->autocommit(false);
    }

    public function query($sql) {
        return $this->connection->query($sql);
    }
}


$dbOne = new SQL();
$dbOne->connectToDatabase('localhost', 'user', 'pass', 'db1');
$result = $dbOne->query("update tab set col = 'val'");

$dbTwo = new SQL();
$dbTwo->connectToDatabase('localhost', 'user', 'pass', 'db2');
$result = $dbTwo->query("update tab set col = 'val'");
?>

This simple example would be able to tell if a fatal error happened in
the script and only allow the db connections to commit their
transactions if there was no error. There is no way to do this now in
php 5.1 (I realize I could achieve a similar affect by storing all the
open connections and calling some other method from the ob handler, but
then the destructors have no real purpose if not for cleanup based on
the exit status of a script). The original example of this "bug" is
really just pointing out contradicting functionality. I would assume
that output buffering would not be allowed in destructors (as it is not
allowed in output buffering handlers). If by waiting for all variables
to go out of scope before the buffer flush, then there is even a bigger
contradiction.





------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=33910&edit=1

Reply via email to