Making old PEAR packages (more) E_STRICT compatible

From: Date: Fri, 21 Sep 2007 23:11:30 +0000
Subject: Making old PEAR packages (more) E_STRICT compatible
Groups: php.pear.dev 
Request: Send a blank email to pear-dev+get-48104@lists.php.net to get a copy of this message
New major packages and new major releases are required to be E_STRICT compatible, and PEAR2 is visible in the horizon. But a lot of existing PEAR packages will probably be around for quite a while yet. This is a proposal on how to fix the existing PHP4-compatible PEAR packages in a way so that they remain PHP4 compatible but can also be used from PHP5 with E_STRICT error reporting enabled. It still requires some effort by the user, but at least the old packages no longer prevent people from turning on E_STRICT error reporting. Using a custom error handler one can mute E_STRICT errors from non-E_STRICT-compliant code, e.g. PEAR. Our error handler begins with something like this: if ($errorNumber == E_STRICT &&
    (strpos($fileName, '/pear/') !== false ||
     preg_match('/^Non-static method (DB|HTTP|Mail|PEAR)::/',
                $message))) {
    return;
} However, when using an opcode cache, some warnings cannot be muted this way. I don't know much about the inner workings of an opcode cache, but using Xcache I have found two types of warnings that are triggered before I have a chance to register my own error handler: #1. "Strict Standards: Assigning the return value of new by reference is deprecated." This is caused by code like "$foo =& new Bar()". #2. "Strict Standards: Declaration of Bicycle::foo() should be compatible with that of Vehicle::foo()". This happens when a method is overridden in a child class, but the two methods take a different number of arguments or similar. These two types of errors are often easy to fix. In many cases, the fix for #1 is to simply replace =& with =. #2 may be fixed by adding dummy parameters to one of the methods. Previously I have manually made these fixes to PEAR packages in order to be able to use PEAR and run with E_STRICT error reporting. The package owners of Mail, Net_SMTP and DB liked the idea and made changes in official release: http://pear.php.net/bugs/bug.php?id=9947 http://pear.php.net/bugs/bug.php?id=11581 This has been very helpful. Now the only problem for me is the last lines of PEAR::raiseError(). The solution here is a bit more tricky, because here it is not possible to simply replace &= with =. A possible solution is to enclose the offending lines in an eval() call, or at least do it for PHP4, i.e. something like this: if (intval(PHP_VERSION) >= 5) {
    if ($skipmsg) {
        $a = new $ec($code, $mode, $options, $userinfo);
    } else {
        $a = new $ec($message, $code, $mode, $options, $userinfo);
    }
} else {
    if ($skipmsg) {
        eval('$a = &new $ec($code, $mode, $options, $userinfo);');
    } else {
        eval('$a = &new $ec($message, $code, $mode, $options, $userinfo);');
    }
} My suggestion is to encourage package owners to avoid using the constructs #1 and #2. As mentioned, this is often quite easy. In particular, the PEAR package should avoid them, as this is required by all other packages. I don't know whether the inability to mute all strict errors is specific to Xcache, or whether other opcode caches have the same problem. It has been a while since a ran without an opcode cache, but AFAIR there weren't any problems back then. Also, I don't know whether there are other constructs that has to be avoided, but so far I don't think I have met any. If somebody knows of other ways of solving this problem, I'd be interested in hearing about them. What to you think of this? Christian

« previous php.pear.dev (#48104) next »