Thank you very much Matthew for your detailed answer!
For those who are interested:
I try that way:
* Rewrite your error -> exception handler to be selective about which
errors it throws as exceptions
I think to convert PHP-Errors into Exceptions has some advantages, because you
could handle them with the error-handler plug-in.
(See http://framework.zend.com/manual/en/zend.controller.plugins.html =>
ErrorController)
So you got one handler (the plug-in) which handles all your Errors and
Exceptions in one place - very elegant.
My solution is (First tests work - but no guarantees!):
My solution is based on: " error_reporting() == 0 " => if it is 0 then it was
a suppressed error by the @-operator!
In the Bootstrap-File:
My_Errorhandler::getInstance();
// The Handler-Class:
class My_Errorhandler
{
static private $_instance = false;
private $_oldErrorhandler = null;
private function __construct()
{
$this->_oldErrorhandler = set_error_handler(array($this,
'newErrorhandler'));
}
static public function getInstance()
{
if (!self::$_instance instanceof self) {
self::$_instance = new self();
}
return self::$_instance;
}
public function newErrorhandler($code, $message, $file, $line)
{
// if error_reporting() == 0 then it was a
// suppressed error with the @-operator!
//(We don't want to handle that kind of errors!)
if (error_reporting() != 0) {
$message .= PHP_EOL . 'Type: ' . $this->_getErrorType($code) .
PHP_EOL;
throw new Ikj_ErrorhandlerException($message, $code, $file, $line);
}
}
private function _getErrorType($errorNo)
{
$errortype = array (
E_ERROR => 'Error',
E_WARNING => 'Warning',
E_PARSE => 'Parsing Error',
E_NOTICE => 'Notice',
E_CORE_ERROR => 'Core Error',
E_CORE_WARNING => 'Core Warning',
E_COMPILE_ERROR => 'Compile Error',
E_COMPILE_WARNING => 'Compile Warning',
E_USER_ERROR => 'User Error',
E_USER_WARNING => 'User Warning',
E_USER_NOTICE => 'User Notice',
E_STRICT => 'Runtime Notice',
E_RECOVERABLE_ERROR => 'Catchable Fatal Error'
);
return $errortype[$errorNo];
}
}
//And a Exception Class:
class Ikj_ErrorhandlerException extends Exception
{
public function __construct($message = null, $code = 0, $file = null, $line
= null)
{
parent::__construct($message, $code);
$this->file = $file;
$this->line = $line;
}
}
Best regards
Sascha
-----Ursprüngliche Nachricht-----
Von: Matthew Weier O'Phinney [mailto:[EMAIL PROTECTED]
Gesendet: Dienstag, 4. Dezember 2007 18:09
An: [email protected]
Betreff: Re: [fw-general] Zend Framework 1.0.3 Problems with
Zend_Loader::isReadable($filename) and initial View Helpers
-- [EMAIL PROTECTED] <[EMAIL PROTECTED]> wrote
(on Tuesday, 04 December 2007, 05:15 PM +0100):
> Hello together,
>
> I experienced a problem with Zend_Loader in the new ZF release. With
> the new release ZF does not found the initial Viewhelpers. It searches
> first in the application\views\helpers and not in the Zend\View\Helper
> directory. I got following error message:
>
> exception 'My_ErrorhandlerException' with message
My guess is that you're being too strict in the above class. Let me
guess: you're throwing certain PHP errors as exceptions?
The issue is that @ still throws errors for a number of language
constructs (include and the various f* file functions for instance).
When display_errors is on, they may or may not be displayed, but if you
have a registered error handler, that handler will still capture the
event.
What this means for most developers is nothing; if they don't register a
PHP error handler, or if such a handler simply logs or mails reports,
execution will continue as normal -- meaning that isReadable() returns
normally. (I have view scripts in my default module as well as in other
modules, and they work fine with this incarnation of Zend_Loader).
However, for those doing clever things like the above, it means that
you'll need to do a little work in your error handler, and throw
exceptions selectively.
As an example:
class My_ErrorhandlerException extends Exception
{
public static function handle($errno, $errstr, $errfile = null,
$errline = null, $errcontext = null)
{
if (!preg_match('/fopen.*helpers/', $errstr)) {
throw new self($errstr, $errno);
}
}
}
Now, some explanation on why we're unlikely to change Zend_Loader below,
in response to your analysis.
> 'fopen(..\application\views\helpers\Url.php) [<a
> href='function.fopen'>function.fopen</a>]: failed to open stream: No
> such file or directory' in D:\www\library\Zend\Loader.php:194
>
> The problem seems to be related with the new
> Zend_Loader::isReadable($filename) method. If I replace the code of
> this method with the old code from the ZF v1.0.2 it works fine. I
> guess the problem is the @ before fopen, it does not suppress the
> error in E_ALL|E_STRICT mode. The function is_readable() was better,
> because it throws no error and returns only false or true.
The problem solved in 1.0.3 was performance. A number of people had
diagnosed Zend_Loader::isReadable() as a performance bottleneck. I did
some analysis of the method, and tried a number of solutions, with the
one in 1.0.3 being the fastest.
The is_readable() solution seems most straightforward... until you look
at the rest of the method. is_readable() does not search the
include_path, which means that in order to determine if a passed
filename (which may include some path elements) was readable, we had to
manually loop over the include_path and test the filename against it
until we found a match... or didn't.
For small include paths -- 1-3 paths -- this isn't a big deal. However,
for more include_path segments, performance decreases factorially -- due
to the number of stat calls it has to make. This is even more of an
issue on systems like Mac where I/O calls are really expensive.
In PHP 5, a third flag was added to fopen(), which allows it to search
the include_path. This solution, with even 3 paths, is over 4 times
faster than looping over the include_path in PHP user code. Consider how
many times Zend_Loader::isReadable() may be called during an
application, and that difference -- which gets larger with the more
include_paths added -- can actually be pretty big.
The downside is that it needs error suppression to ensure that errors
are not reported. Unfortunately, as you encountered, the nature of error
suppression is somewhat flaky for a number of functions in PHP when
combined with custom error handlers, and this happens to be one of them.
So, you have three paths to take:
* Maintain a fork of Zend_Loader that will play nice with your error ->
exception handler
* Rewrite your error -> exception handler to be selective about which
errors it throws as exceptions
* Disable your error -> exception handler
I used to really like the idea of throwing PHP errors as exceptions.
However, there are a ton of cases like this where unexpected things
happen, which make using them a bit of a nightmare. I'd personally go
with the third item on the list (disable it).
--
Matthew Weier O'Phinney
PHP Developer | [EMAIL PROTECTED]
Zend - The PHP Company | http://www.zend.com/
_____________________________________________________________________
Der WEB.DE SmartSurfer hilft bis zu 70% Ihrer Onlinekosten zu sparen!
http://smartsurfer.web.de/?mc=100071&distributionid=000000000066