Making old PEAR packages (more) E_STRICT compatible
| From: | Christian Schmidt | 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