I'm already set its debugging option to true,but when there's error in smarty template(i.e. there is no corresponding plugin for a specific smarty_modifier),nothing is output for information.
UPDATE
For anyone that wants to have a try,this is the most simple template I can think of :
{$var|nosuch_modifier}
1- First, you can check if error_reporting is on. this is usually done in php.ini but you can place these statements on top of your php source.
ini_set('display_errors', 1);
ini_set('error_reporting', E_ALL);
and make sure it is not disabled elsewhere.
2- smarty may report errors as throwing an exception. You can define a global exception handler to catch them, here is an example;
try {
// place your code here
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
Update upon comments:
The only reason I can think of is that you've set compile_check to false.
$tpl->compile_check = false;
In this case, Smarty will show the latest compiled source, whatever you do to the tpl file. So, did you check and set compile_check to true?
$tpl->compile_check = true;
Try
ini_set('display_errors', true);
error_reporting(E_ALL);
in the PHP code.
Smarty error reporting can be set manually.
$smarty->error_reporting = E_ALL ^ E_NOTICE;
Some comments from the Smarty.class.php
error muting is done because some people implemented custom
error_handlers using http://php.net/set_error_handler and for some
reason did not understand the following paragraph:
It is important to remember that the standard PHP error handler is
completely bypassed for the error types specified by error_types
unless the callback function returns FALSE. error_reporting() settings
will have no effect and your error handler will be called regardless -
however you are still able to read the current value of
error_reporting and act appropriately. Of particular note is that this
value will be 0 if the statement that caused the error was prepended
by the # error-control operator.
Smarty deliberately uses #filemtime() over file_exists() and
filemtime() in some places. Reasons include
- #filemtime() is almost twice as fast as using an additional file_exists()
- between file_exists() and filemtime() a possible race condition is opened, which does not exist using the simple #filemtime() approach.
Related
I am using some external libraries which uses the # error silencing operator.
The library is generating some errors and it becomes difficult to point the exact location where the error occurs as the # operator hides it.
Is there any way to easily disable the #-operator in the code without making any actual changes to the code?
I have tried Scream Pecl extension but it does not seem to work. It's available for PHP 5.6 version while I am using PHP 7.
Scream extension is installed and is enabled in php.ini by using scream.enabled=1 (as per their documentation) but the error still doesn't show or log.
You cannot disable the behaviour of the # symbol, but you can log/handle these errors nonetheless by using your own error handler.
From the docs:
If you have set a custom error handler function with set_error_handler() then it will still get called,
What this operator does is basically set error_reporting to 0 for one statement. Which is also reflected on the same docs:
but this custom error handler can (and should) call error_reporting() which will return 0 when the call that triggered the error was preceded by an #.
So, assuming you could have something like this very simple implementation, you would need to fine tune the details:
function exceptional_error_handler($severity, $message, $file, $line)
{
if (error_reporting() === 0) {
// assuming your application always runs with `error_handling !== 0`,
// e.g. by setting this during application bootstrap
// that we got here means this is was a "silenced" error
throw new \ErrorException("Silenced error! '$message'", 0, $severity, $file, $line);
}
// regular (non-silenced) errors should respect your error_reporting levels
if (!(error_reporting() & $severity)) {
// This error code is not included in error_reporting
return;
}
// everything else is converted to an exception
throw new \ErrorException($message, 0, $severity, $file, $line);
}
set_error_handler("exceptional_error_handler");
This converts all errors to exceptions, simply noting with a different message when it was a "silenced" error, but your error handler could do logging or have any kind of custom logic.
By doing this, you could leave the existing/third party code untouched, and just add the error handling logic to the bootstrapping part of your application.
Docs for set_error_handler().
Let's suppose I have this piece of code, where I try to make sure all my errors are reported in some way, yet the visitors won't have to see but a nice page apologizing for the situation.
ini_set('display_errors', 'off');
error_reporting(E_ALL);
set_exception_handler('exceptionHandler');
function exceptionHandler($error)
{
// functionWithSyntaxError()
undefinedFunction();
echo $error->getMessage();
}
If I would have functionWithSyntaxError() uncommented, I would see the error about the syntax. I guess that's because the code is not even run and the compiler doesn't care about my exception handler or other directives.
Now, if I comment it back and leave only undefinedFunction(), I wouldn't be able to log the error about the undefined function, either would my code run further. I wouldn't know what happens so I would have to set display_errors ON, in which case I would defy my original purpose of not displaying errors, but reporting them silently.
So, in this case I guess the compiler doesn't check for undefined function as it does with the syntax. What happens in this case? It certainly doesn't continue either. Shouldn't the code go in a loop? What happens under the hood?
I know I have better options to handle errors gracefully, defining a debug mode (where errors will be displayed), for example, but I just want to understand the intricacies of this situation
The PHP documentation reads (emphasis mine):
The error_reporting() function sets the error_reporting directive at
runtime. PHP has many levels of errors, using this function sets that
level for the duration (runtime) of your script. If the optional level
is not set, error_reporting() will just return the current error
reporting level.
Does that mean that the level of error reporting can only be set once in a PHP script, and not changed afterwards? For instance, is it possible to do this:
error_reporting(0);
try {
errorSilently();
} catch (Exception $e) {
// Do nothing
}
error_reporting(E_ALL);
try {
errorLOUDLY();
} catch (Exception $e) {
// Do nothing
}
Note that I wrote a // Do nothing because it seems that if an error is thrown, Apache writes it to its error_log any way, if it's caught or not. What I want to do is disable that behaviour, and not write to the error log.
Yes, you can change the error reporting level at any time during your program's runtime, and it will stay at that new level until you change it again. You can "silence" only specific parts. Note that error_reporting() returns the old level, specifically so you can do things like:
$previous = error_reporting(0);
something_which_produces_warnings_which_can_safely_be_ignored();
error_reporting($previous);
To also temporarily disable error logging you may have to ini_set('log_errors', false).
And no, try..catch has nothing to do with error reporting. Those are separate mechanisms. error_reporting influences errors triggered by trigger_error; try..catch is a mechanism for handling exceptions thrown via throw.
I'm running a PHP script every night using a cron service. Everything it outputs will be printed to an log file for debug prepossess. The file I use will retrieve xml's from a different site using the function 'file_get_contents()'. But the function can return an error which I really don't want to see as I am already showing a custom error.
Quick example of my piece of code:
$buffer = #file_get_contents('http://xx:xx#xx/xml/xx?offset=2') or print('retry in 5 seconds');
if($buffer === false) {
sleep(5);
$buffer = #file_get_contents('http://xx:xx#xx/xml/xx?offset=2') or print('error notice');
}
The problem is the first one will trigger an error and print it'll retry in 5 seconds. How can I correctly suppress the thrown error?
I have an error handler, but I prefer not to catch this error separately.
Edited:
My solution wasn't to change the error_reporting, but to catch the error message. If it starts with 'file_get_contents()', no error will be thrown. This is not the best way, but will do the job for me.
You can try inserting this at the start:
error_reporting(0);
Then after the code with the error/warning:
error_reporting(E_ALL ^ E_WARNING);
Okay, never ever use the #-operator.
In PHP you have two options available: either use a custom error handler or use try/catch.
Since file_get_contents doesn't throw an exception, you can only use the first approach.
You can set an error handler like this: http://php.net/set-error-handler and then act correctly (log something or return a custom error code).
If you just want to turn of all errors use error_reporting(0) or if you just want to turn off a specific category use error_reporting(E_ALL ^ E_WARNING) (all but warnings) or specifcy them explicitely error_reporting(E_WARNING | E_NOTICE) (warnings and notices).
I prefer the first approach, since when you just disable it you have no idea of what's going on in your code.
Add # before command or use try catch.
I have a custom error handler attached to E_ALL PHP errors.
In an external lib the call $row = #mysql_fetch_assoc($this->result); triggers PHP Warnings caught by my handler. Why? Shouldn't '#' make PHP ignore this?
My question: Is there any way I can detect (in my error handler) that '#' was used?
Referencing the PHP Manual on set_error_handler shows
It is important to remember that the
standard PHP error handler is
completely bypassed. error_reporting()
settings will have no effect and your
error handler will be called
regardless - however you are still
able to read the current value of
error_reporting and act appropriately.
Of particular note is that this value will be 0 if the statement that
caused the error was prepended by the
# error-control operator.
So you could do this:
function my_error_handler($errno, $errstr) {
if (error_reporting() == 0) { // called with #
return;
}
//....
}
A quick look into the PHP manual revealed this:
It is important to remember that the
standard PHP error handler is
completely bypassed. error_reporting()
settings will have no effect and your
error handler will be called
regardless - however you are still
able to read the current value of
error_reporting and act appropriately.
Of particular note is that this value will be 0 if the statement that
caused the error was prepended by the
# error-control operator.
http://de.php.net/manual/en/function.set-error-handler.php
Using the # operator is considered bad style by quite some people, btw.