I have seen uses of # in front of certain functions, like the following:
$fileHandle = #fopen($fileName, $writeAttributes);
What is the use of this symbol?
It suppresses error messages — see Error Control Operators in the PHP manual.
It suppresses errors.
See Error Control Operators in the manual:
PHP supports one error control operator: the at sign (#). When prepended to an expression in PHP, any error messages that might be generated by that expression will be ignored.
If you have set a custom error handler function with set_error_handler() then it will still get called, 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 #...
The # symbol is the error control operator (aka the "silence" or "shut-up" operator). It makes PHP suppress any error messages (notice, warning, fatal, etc) generated by the associated expression. It works just like a unary operator, for example, it has a precedence and associativity. Below are some examples:
#echo 1 / 0;
// generates "Parse error: syntax error, unexpected T_ECHO" since
// echo is not an expression
echo #(1 / 0);
// suppressed "Warning: Division by zero"
#$i / 0;
// suppressed "Notice: Undefined variable: i"
// displayed "Warning: Division by zero"
#($i / 0);
// suppressed "Notice: Undefined variable: i"
// suppressed "Warning: Division by zero"
$c = #$_POST["a"] + #$_POST["b"];
// suppressed "Notice: Undefined index: a"
// suppressed "Notice: Undefined index: b"
$c = #foobar();
echo "Script was not terminated";
// suppressed "Fatal error: Call to undefined function foobar()"
// however, PHP did not "ignore" the error and terminated the
// script because the error was "fatal"
What exactly happens if you use a custom error handler instead of the standard PHP error handler:
If you have set a custom error handler function with
set_error_handler() then it will still get called, 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 #.
This is illustrated in the following code example:
function bad_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
echo "[bad_error_handler]: $errstr";
return true;
}
set_error_handler("bad_error_handler");
echo #(1 / 0);
// prints "[bad_error_handler]: Division by zero"
The error handler did not check if # symbol was in effect. The manual suggests the following:
function better_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
if(error_reporting() !== 0) {
echo "[better_error_handler]: $errstr";
}
// take appropriate action
return true;
}
Also note that despite errors being hidden, any custom error handler (set with set_error_handler) will still be executed!
Like already some answered before: The # operator suppresses all errors in PHP, including notices, warnings and even critical errors.
BUT: Please, really do not use the # operator at all.
Why?
Well, because when you use the # operator for error supression, you have no clue at all where to start when an error occurs. I already had some "fun" with legacy code where some developers used the # operator quite often. Especially in cases like file operations, network calls, etc. Those are all cases where lots of developers recommend the usage of the # operator as this sometimes is out of scope when an error occurs here (for example a 3rdparty API could be unreachable, etc.).
But what's the point to still not use it? Let's have a look from two perspectives:
As a developer: When # is used, I have absolutely no idea where to start. If there are hundreds or even thousands of function calls with # the error could be like everyhwere. No reasonable debugging possible in this case. And even if it is just a 3rdparty error - then it's just fine and you're done fast. ;-) Moreover, it's better to add enough details to the error log, so developers are able to decide easily if a log entry is something that must be checked further or if it's just a 3rdparty failure that is out of the developer's scope.
As a user: Users don't care at all what the reason for an error is or not. Software is there for them to work, to finish a specific task, etc. They don't care if it's the developer's fault or a 3rdparty problem. Especially for the users, I strongly recommend to log all errors, even if they're out of scope. Maybe you'll notice that a specific API is offline frequently. What can you do? You can talk to your API partner and if they're not able to keep it stable, you should probably look for another partner.
In short: You should know that there exists something like # (knowledge is always good), but just do not use it. Many developers (especially those debugging code from others) will be very thankful.
Suppose we haven't used the "#" operator then our code would look like this:
$fileHandle = fopen($fileName, $writeAttributes);
And what if the file we are trying to open is not found? It will show an error message.
To suppress the error message we are using the "#" operator like:
$fileHandle = #fopen($fileName, $writeAttributes);
# suppresses error messages.
It is used in code snippets like:
#file_get_contents('http://www.exaple.com');
If domain "http://www.exaple.com" is not accessible, an error will be shown, but with # nothing is shown.
If the open fails, an error of level E_WARNING is generated. You may use # to suppress this warning.
PHP supports one error control operator: the at sign (#). When prepended to an expression in PHP, any error messages that might be generated by that expression will be ignored.
If you have set a custom error handler function with set_error_handler() then it will still get called, 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 #.
<?php
/* Intentional file error */
$my_file = #file ('non_existent_file') or
die ("Failed opening file: error was '$php_errormsg'");
// this works for any expression, not just functions:
$value = #$cache[$key];
// will not issue a notice if the index $key doesn't exist.
?>
Note:-
1) The #-operator works only on expressions.
2) A simple rule of thumb is: if you can take the value of something, you can prepend the # operator to it. For instance, you can prepend it to variables, function and include calls, constants, and so forth. You cannot prepend it to function or class definitions, or conditional structures such as if and foreach, and so forth.
Warning:-
Currently the "#" error-control operator prefix will even disable
error reporting for critical errors that will terminate script
execution. Among other things, this means that if you use "#" to
suppress errors from a certain function and either it isn't available
or has been mistyped, the script will die right there with no
indication as to why.
It might be worth adding here there are a few pointers when using the # you should be aware of, for a complete run down view this post: http://mstd.eu/index.php/2016/06/30/php-rapid-fire-what-is-the-symbol-used-for-in-php/
The error handler is still fired even with the # symbol prepended, it just means a error level of 0 is set, this will have to be handled appropriately in a custom error handler.
Prepending a include with # will set all errors in the include file to an error level of 0
# suppresses the error message thrown by the function. fopen throws an error when the file doesn't exit. # symbol makes the execution to move to the next line even the file doesn't exists. My suggestion would be not using this in your local environment when you develop a PHP code.
Related
I have seen uses of # in front of certain functions, like the following:
$fileHandle = #fopen($fileName, $writeAttributes);
What is the use of this symbol?
It suppresses error messages — see Error Control Operators in the PHP manual.
It suppresses errors.
See Error Control Operators in the manual:
PHP supports one error control operator: the at sign (#). When prepended to an expression in PHP, any error messages that might be generated by that expression will be ignored.
If you have set a custom error handler function with set_error_handler() then it will still get called, 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 #...
The # symbol is the error control operator (aka the "silence" or "shut-up" operator). It makes PHP suppress any error messages (notice, warning, fatal, etc) generated by the associated expression. It works just like a unary operator, for example, it has a precedence and associativity. Below are some examples:
#echo 1 / 0;
// generates "Parse error: syntax error, unexpected T_ECHO" since
// echo is not an expression
echo #(1 / 0);
// suppressed "Warning: Division by zero"
#$i / 0;
// suppressed "Notice: Undefined variable: i"
// displayed "Warning: Division by zero"
#($i / 0);
// suppressed "Notice: Undefined variable: i"
// suppressed "Warning: Division by zero"
$c = #$_POST["a"] + #$_POST["b"];
// suppressed "Notice: Undefined index: a"
// suppressed "Notice: Undefined index: b"
$c = #foobar();
echo "Script was not terminated";
// suppressed "Fatal error: Call to undefined function foobar()"
// however, PHP did not "ignore" the error and terminated the
// script because the error was "fatal"
What exactly happens if you use a custom error handler instead of the standard PHP error handler:
If you have set a custom error handler function with
set_error_handler() then it will still get called, 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 #.
This is illustrated in the following code example:
function bad_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
echo "[bad_error_handler]: $errstr";
return true;
}
set_error_handler("bad_error_handler");
echo #(1 / 0);
// prints "[bad_error_handler]: Division by zero"
The error handler did not check if # symbol was in effect. The manual suggests the following:
function better_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
if(error_reporting() !== 0) {
echo "[better_error_handler]: $errstr";
}
// take appropriate action
return true;
}
Also note that despite errors being hidden, any custom error handler (set with set_error_handler) will still be executed!
Like already some answered before: The # operator suppresses all errors in PHP, including notices, warnings and even critical errors.
BUT: Please, really do not use the # operator at all.
Why?
Well, because when you use the # operator for error supression, you have no clue at all where to start when an error occurs. I already had some "fun" with legacy code where some developers used the # operator quite often. Especially in cases like file operations, network calls, etc. Those are all cases where lots of developers recommend the usage of the # operator as this sometimes is out of scope when an error occurs here (for example a 3rdparty API could be unreachable, etc.).
But what's the point to still not use it? Let's have a look from two perspectives:
As a developer: When # is used, I have absolutely no idea where to start. If there are hundreds or even thousands of function calls with # the error could be like everyhwere. No reasonable debugging possible in this case. And even if it is just a 3rdparty error - then it's just fine and you're done fast. ;-) Moreover, it's better to add enough details to the error log, so developers are able to decide easily if a log entry is something that must be checked further or if it's just a 3rdparty failure that is out of the developer's scope.
As a user: Users don't care at all what the reason for an error is or not. Software is there for them to work, to finish a specific task, etc. They don't care if it's the developer's fault or a 3rdparty problem. Especially for the users, I strongly recommend to log all errors, even if they're out of scope. Maybe you'll notice that a specific API is offline frequently. What can you do? You can talk to your API partner and if they're not able to keep it stable, you should probably look for another partner.
In short: You should know that there exists something like # (knowledge is always good), but just do not use it. Many developers (especially those debugging code from others) will be very thankful.
Suppose we haven't used the "#" operator then our code would look like this:
$fileHandle = fopen($fileName, $writeAttributes);
And what if the file we are trying to open is not found? It will show an error message.
To suppress the error message we are using the "#" operator like:
$fileHandle = #fopen($fileName, $writeAttributes);
# suppresses error messages.
It is used in code snippets like:
#file_get_contents('http://www.exaple.com');
If domain "http://www.exaple.com" is not accessible, an error will be shown, but with # nothing is shown.
If the open fails, an error of level E_WARNING is generated. You may use # to suppress this warning.
PHP supports one error control operator: the at sign (#). When prepended to an expression in PHP, any error messages that might be generated by that expression will be ignored.
If you have set a custom error handler function with set_error_handler() then it will still get called, 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 #.
<?php
/* Intentional file error */
$my_file = #file ('non_existent_file') or
die ("Failed opening file: error was '$php_errormsg'");
// this works for any expression, not just functions:
$value = #$cache[$key];
// will not issue a notice if the index $key doesn't exist.
?>
Note:-
1) The #-operator works only on expressions.
2) A simple rule of thumb is: if you can take the value of something, you can prepend the # operator to it. For instance, you can prepend it to variables, function and include calls, constants, and so forth. You cannot prepend it to function or class definitions, or conditional structures such as if and foreach, and so forth.
Warning:-
Currently the "#" error-control operator prefix will even disable
error reporting for critical errors that will terminate script
execution. Among other things, this means that if you use "#" to
suppress errors from a certain function and either it isn't available
or has been mistyped, the script will die right there with no
indication as to why.
It might be worth adding here there are a few pointers when using the # you should be aware of, for a complete run down view this post: http://mstd.eu/index.php/2016/06/30/php-rapid-fire-what-is-the-symbol-used-for-in-php/
The error handler is still fired even with the # symbol prepended, it just means a error level of 0 is set, this will have to be handled appropriately in a custom error handler.
Prepending a include with # will set all errors in the include file to an error level of 0
# suppresses the error message thrown by the function. fopen throws an error when the file doesn't exit. # symbol makes the execution to move to the next line even the file doesn't exists. My suggestion would be not using this in your local environment when you develop a PHP code.
in my code is usually use if(!isset()) for set default value if the variable is empty
ex :
if(isset($_POST['noreg']))
{
$noreg = $_POST['noreg'];
}
else
{
$noreg = 'empty';
}
my friend suggest me to use elvis operator with error handling, and it looks shorten than before,
$noreg = #$_POST['noreg'] ?: 'empty';
it works fine like my old code
but is it safe or it has any risk if i use it?
can anyone help me for this?
thanks
The # operator suppresses error reporting. That means there's still an error being produced, but it's being silenced. That's problematic for three reasons:
It's probably slower to raise and then discard an error than an isset check would be.
If you have a custom error handler, that handler may ignore # and still produce an error.
You have no idea what other kinds of errors you may be suppressing that you're not expecting.
Particularly, what if you accidentally write #$_PSOT['noreg']? PHP's error reporting won't be alerting you to this mistake and you're in the dark. If you'd use filter_input(INPUT_POST, 'noreg') or array_key_exists('noreg', $_POST), such mistakes could not be made.
(This example may be a bit contrived since isset() will suppress the same error, but it's to illustrate the pitfalls of using error suppression and why one must be very conscious of it.)
If you use it for simple variable initialization then it's ok. It will work on any expression & when preceding it, it will suppress the error.
Straight from documentation http://php.net/manual/en/language.operators.errorcontrol.php
PHP supports one error control operator: the at sign (#). When
prepended to an expression in PHP, any error messages that might be
generated by that expression will be ignored.
If you have set a custom error handler function with
set_error_handler() then it will still get called, 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 #.
Currently the "#" error-control operator prefix will even disable
error reporting for critical errors that will terminate script
execution. Among other things, this means that if you use "#" to
suppress errors from a certain function and either it isn't available
or has been mistyped, the script will die right there with no
indication as to why.
Context:
I have three environments for an app: dev (local), test/staging (prod server), production. The app knows which is which. Error reporting on both staging and production is 0, so errors are never shown. On dev I want to see errors immediately and I want to see them where they happen, so not in some log, but in the code's result.
However, I don't want to see the errors I have explicitly suppressed with #. I've been using fsockopen and that throws a warning when it can't connect. I accept the no-connection, but don't want to see the error. Not even on dev.
Apparantly all errors go though the custom error handler, even if they were suppressed in the code.
My error handler has only 4 arguments: errno, error, file, line. From those I can't see whether the error was originally suppressed or not. If I can see that there, I can choose whether to print the error (right now I always do, if env=dev).
Any ideas? Or maybe on how to completely ignore suppressed errors (so that they don't even reach the custom error handler)?
There's a hint to this in the set_error_handler manual page.
[the error_reporting()] value will be 0 if the statement that caused the error was
prepended by the # error-control operator
When you use the error control operator #, what is happening is this:
error reporting is set to 0 (no errors) - error_reporting(0)
the expression is evaluated
error reporting is set back to the previous value (ie turned back on)
The slightly confusing quote above refers to the fact that error_reporting returns the current setting. If you have suppressed the error with the control operator, calling error_reporting() will return 0.
Therefore, if you know you have set it to non-zero (ie you are reporting some errors) and it returns zero, you know the error was suppressed.
If you detect a suppressed error and want to know what it was, you can find it in the variable $php_errormsg (if track_errors is set to true in php.ini).
Note that the error control operator causes a lot of overhead, as it changes the error reporting level twice each time it is used. It will slow down your script.
A proper way to handle errors in php
do not use error_reporting
install an errors-to-exceptions handler ( http://www.php.net/manual/en/class.errorexception.php , example 1) and convert all php "errors" to exceptions
in your main code, use try-catch where appropriate
install an exception handler to catch exceptions not caught in the main code. This handler is the only place where you output and/or log errors.
do not use #. In a rare case you want to ignore an error, use an empty catch block
use some stupid trick to catch "fatal" errors. Better yet, contact php group and try to convince them to make "fatal" errors handleable in scripts.
For PHP 8.0
So in PHP 8.0, you can no longer tell if the error/warning/notice, etc, was suppressed (using #) simply by checking if error_reporting() == 0.
Instead, it is now a fairly long piece of bitwise operators with constants, described in a warning box here: https://www.php.net/manual/en/language.operators.errorcontrol.php
Fix for both PHP 7.x and 8.x
In your custom error handler, if you want to tell if your error was suppressed with the # sign, use something like this:
$PHP_8_SUPPRESSED = E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE;
$er = error_reporting();
if ($er === 0 || $er === $PHP_8_SUPPRESSED) {
// do code because it was suppressed. Ex: return FALSE, etc.
}
At the time of this writing, $PHP_8_SUPPRESSED will equal integer value 4437, but it's probably best not to hard-code that, since future versions of PHP might change these constant values.
Quick side note: I really wish they had just created a new constant called "E_SUPPRESSED_ERROR" or something like that we could check. But sadly they did not!
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Reference - What does this symbol mean in PHP?
I'm making a web application that uses URL queries to access different parts of the application. I was looking for a solution to make an invalid query like index.php?page=dashboarrrd display an error 404 message instead of a PHP error.
After some searching, I found that I could use something like the following to do the job:
if(!#include($fileName)){
#include("pageData/404.php");
}
And that makes sense, but I don't know why that works. I mean, what the heck does the # before the include mean? I totally understand include $filename; but I need an explanation for #include ($fileName)
the code you really need is
$fileName = "pagedata/".basename($_GET['page']).".php";
if(is_readable($fileName)) {
include($fileName);
} else {
include("pagedata/404.php");
}
and # has absolutely nothing to do here
# is one of biggest delusions coming from lack of experience.
Ones who using it do expect only one kind of error, while in fact there can be many more. And to gag ALL possible messages to suppress only one of them is definitely like to throw out the child along with the bath.
There is a fundamental problem that makes such misunderstanding so widespread:
Most PHP users cannot distinguish three sides of error control:
error handling
error reporting
user notification.
Most of time in sake of [3] people mess with (1) and (2). While each of them require separate treatment:
your program should raise no intentional errors. No error should be part of program logic. All errors that ever raised should be only unexpected ones.
if you expect some error, you have to handle it. Not gag with #, but gracefully handle. is_readable() in my code exactly for that.
error reporting is for the programmer and should be always at max. So, error logging should be enabled on a live site and a programmer have to check all errors occurred. And of course he would be interested in such errors, thus # will do only harm here.
User-level error messages should be different from system ones. Your 404.php is a good example of such user-friendly behavior. As for the system error messages, a user shouldn't be able to see them at all. Just turn display_errors off and see - there is no use for the # again!
This is the # Error Control Operator (quoting) :
When prepended to an expression in
PHP, any error messages that might be
generated by that expression will be
ignored.
In normal conditions, if include cannot load the file you've passed as a parameter, it'll emit a warning.
Prepending the # operator to include will prevent that warning from being emited -- and, so, from being displayed / logged.
So, the following portion of code :
include 'does-not-exist.php';
Will get you the following warnings :
Warning: include(does-not-exist.php) [function.include]: failed to open stream: No such file or directory
Warning: include() [function.include]: Failed opening 'does-not-exist.php' for inclusion
While this line :
#include 'does-not-exist.php';
Will get you not warning.
And, as a sidenote, for information : Five reasons why the shut-op operator (#) should be avoided
The # suppresses errors. This is generally discouraged, as when developing you want to see errors.
Errors are easy to suppress when moving to a production environment with the display_errors setting to off. So yea, in most cases, there really is no need for the error to be suppressed.
EDIT
As an extra tidbit to "improve" that, what I used to do when dynamically including a file, is have an array which acts as a "white list" of valid requests. This does not "have" to be an array, just what I chose to do an example with.
$whiteList = array('filename1', 'index', 'home', 'about');
if (in_array($filename, $whiteList)) {
include($filename);
}else {
include('page/404.php');
}
This would do a few things, 1 make you not need the error suppressor. Two, it would make it a bit more securer, as without this, you would need to do a basename call to filter the text to prevent certain type of include injections etc. (Not knowing if you did this already, just extra information).
So yea, you may want analyze / look at other ways to achieve this and above is just one method :)
The use of "#" simply suppresses the error that would normally result from (in this instance) a missing file. Whilst generally its use is a very bad idea, there are some rare exceptions, such as the code snippet you provide above.
For more information, see the Error Control Operators section of the PHP manual.
Additionally, you might find the existing Reference - What does this symbol mean in PHP? question worthy of a quick scan.
The # in php suppresses all error output. For instance, if you had error reporting for warnings, an # in front of a function that generated a warning would not display the warning text.
include is an example of such a construct. If the included file is not found, it will display a warning saying so. The # is not necessary in the code at all, it is just there so that the user will not see warnings.
However, it is better to use apache (or php if you prefer) to change ini for displaying errors on the development site and not displaying them on the production site. That would make the # symbol useless.
A better question is why you need to do this 404 include. Why are you including a file for display? Why not have apache handle 404 redirects on its own? Why wouldn't the file exist in the first place?
# suppresses error messages. The parentheses are optional in include, but whoever wrote that snippet included them.
#include() is the opposite of require(). The first will silently ignore an (optional and missing) include script, while the second will throw an error and halt the script when the (critical) dependency is missing.
In this instance it is only senseful within the if(). The second should preferrably not have an error suppression, as it doesn't mask any seriously security-relevant error message.
I am currently refactoring some code for work and I have come across some function calls prefixed by the "#" symbol. As I understand it, this is intended to escape PHP error reporting if the call fails.
Is this type of thing good practice? I understand the rationale in a development environment but when the site is pushed to production shouldn't all errors be handled properly rather than just escaped?
The use of this symbol would therefore mean that the developer has to sort through the code at a later stage to remove all error reporting escapes.
I am unsure whether to remove these symbols and just find a better way to handle potential errors or not.
For clarity, the function this was used on was the native PHP fsockopen() function.
That's probably among the worst practices you can come across in php code. It basically tells the interpreter to suppress errors and just try to do whatever the code asks it to do regardless of the outcome.
A great way to drag yourself and fellow teammates into all-nighter phantom bug hunts once the app has grown substantially.
Try-catch with custom exception handling is the way to go.
I think it is sometimes understandable to use # for calling functions like fsockopen(), because when they fail they will raise a warning as well as returning false.
There may be cases where you expect these calls to fail regularly and therefore do not want a warning to be raised. Obviously you shouldn't be displaying warnings in production and should be logging them instead, but you might still want to use the # operator to stop your logs getting full. You could stop warnings getting reported at all by changing the error_reporting setting but that is not ideal.
That's called the error control operator, and is generally a very scary thing to consider using. A warning from the manual (the emboldening is mine):
Currently the "#" error-control
operator prefix will even disable
error reporting for critical errors
that will terminate script execution.
Among other things, this means that if
you use "#" to suppress errors from a
certain function and either it isn't
available or has been mistyped, the
script will die right there with no
indication as to why.
Using the "#" operator is very useful when you know that the function call can fail, like, for example, the fsockopen call. Best practice is to use this only when the function you are calling often fails and is a valid case in your application. Also, you should definitely check the return value of the function after calling it:
$fp = #fsockopen($hostname, $port);
if ($fp === false) {
// handle connection failure
}
else {
// handle connection success
}
You should avoid two things:
Not checking the return value;
Using the "#" operator where you don't expect an error -- for example when opening a local file or sending headers. When opening a local file fails, that is an error and it should be handled properly.
Note: you might also want to look at set_error_handler()
if you use your custom error-handlers, the # operator will not help you,
you will always get error-events from situations where your are handling the "Warning" in your code ... like at fsockopen etc.
so you can simple suppress effectively the warning this way:
function renameWithOutExpectedAndSelfHandledErrors( ... ) {
set_error_handler(function(){}); // deactivate all errors
$result = rename('not existing','blafussel');
restore_error_handler(); // restore old error-situation
return $result;
}