Can we use # symbol in variable name php - php

I had an old codesetup from some other developer and I am setting up the same on my server, there I saw a line
<?php #$Days = $_POST['Days']; ?>
This code runs well on my local setup but once I uploaded it on server this did not worked and returned a network error and all the code/HTML after this code also did not work.
Although, I debugged this issue and have removed this. Also, I know that to handle the errors we use the # symbol, and also I have read this question
My query is that what was the error in the above case, why was it not shown, if I want to check the error then what shall I do.
For error reporting I shall tell you that I already used the below code
<?php
ini_set("display_errors", "1");
error_reporting(E_ALL);
?>
So please tell me why was my code unable to get past this statement, as I have around 100's of such code blocks. Is there any setting in php which could help me to get over this.

The # is the error suppression operator in PHP, have a look at the documentation.
In your example, it is used before the variable name to avoid the E_NOTICE error there. If in the $_POST array, the 'Days' key is not set it will throw an E_NOTICE message, but # is used there to avoid that E_NOTICE.
The cause of the code not working on the server is probably due to the scream.enabled directive in your php.ini configuration being disabled.
Disabling scream should fix the issue.
Change the directive in your php.ini, like so:
scream.enabled = 0
If you want to disable it during run-time, then you can use ini_set as stated in the manual:
ini_set('scream.enabled', false);
Edit
Someone in the comments pointed out I haven't been thorough enough with my answer. I will try to amend my mistake in this here edit :).
The reason scream (and disabling the #) can / will break the code is due to the fact that the variable doesn't have a value. If the remainder of the code tries to use the variable it will throw an error.
Also, an E_NOTICE can throw an error if you attach an error handler to it.
A quote from another question:
The above code will throw an ErrorException any time an E_NOTICE or
E_WARNING is raised, effectively terminating script output (if the
exception isn't caught). Throwing exceptions on PHP errors is best
combined with a parallel exception handling strategy
(set_exception_handler) to gracefully terminate in production
environments.

Related

PHP suppress warning with the # character not working on command line

I have an external include file in my php script which triggers a Warning when executing it in the browser. So I put an # character before it and very nice, now the Warning doesn't happen anymore. My problem is that if I now execute the script on the CLI the warning is not suppressed. How can I also suppress the warning for CLI?
This is a new VPS running PHP 7.3.
#include_once('externalsourcefile.php');
Result is:
WARNING : ""continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"?" at line xx (externalsourcefile.php)
UPDATE: the point is that die include file is an external source, which I can't edit to resolve the Warning by my own.
You must refer to https://www.php.net/manual/en/function.include-once.php#84108 , It will give you an idea how include_once works. You must remove # soon as possible, bad practice!
if(include_once('externalsourcefile.php') == false) {
} else {
}
# suppresses warnings for that statement, in your case the actual include_once, not the stuff that happens inside it.
I'm writing this as an answer, because it is too long to put in a comment. Saying that # should never be used is wrong. It's using it without thinking that is wrong.
Consider this simple code being run in a busy multi-process environment:
clearstatcache(true, $pathname);
if(is_dir($pathname) && $dh=opendir($pathname)) {
// readdir() loop here
}else{
// error handling here
}
This code has a race condition. It has happened for me numerous times that the directory has disappeared between the is_dir() return and the opendir() call, leading to warnings on the console:
PHP Warning: opendir(/the/path/in/use): failed to open dir: No such file or directory in /path/to/script.php on line 2
So how could this race be worked around without disabling warnings from opendir(), I ask you?
Disabling globally is IMHO worse than doing it on specific statements like the opendir() call above.
As already said, the error is not caused by the include_once statement itself but by the code running inside the included file (you can determine that by reading carefully the error message).
It should work, anyway. There must be something else going on.
I can think of three possibilities:
The CLI interpreter in your VPS is configured to use a custom error handler that doesn't support the error suppression operator:
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.
The interpreter is configured for debugging and Xdebug has been set up with the xdebug.scream directive:
If this setting is 1, then Xdebug will disable the # (shut-up) operator so that notices, warnings and errors are no longer hidden.
The browser interpreter is running an earlier PHP version then the CLI one. The "continue" targeting switch is equivalent to "break" warning is a backwards-incompatible change in PHP/7.3. It didn't trigger a warning before.
In either case, and as also already noted, the question itself illustrates that suppressing errors can lead to hard-to-diagnose bugs.

PHP: despite disabling all errors, copy() error message still displayed on page

I have:
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
It seems to work but when I use copy() function and try to copy to directory with denied access the error is displayed on the page itself. I don't need it. But I can't intercept copy()'s errors. I tried error_get_last() and try...catch (Exception $e) but still can't intercept it? How can I disable showing copy errors on page and how to intercept them in code?
If catching the copy error is all you need to do then:
set_error_handler(function ($errno, $errstr, $errfile, $errline) {
// Log the error somewhere without spooking the users
return true;
});
copy(...);
restore_error_handler();
This way you can "silence" only this error and keep everything else working as before.
from runtime it is better (and more reliable) to use:
error_reporting(0);
see: http://php.net/manual/en/function.error-reporting.php for more info.
also you can suppress any errors regarding of reporting level by prefixing expression with #:
#copy(...)
see: http://php.net/manual/en/language.operators.errorcontrol.php for more info, also note what this cause a performance drop and causes expression to return boolean false if error occured, regardless of its original return type.
Worth noting:
If you are using nginx+php-fpm (or similar) ini values may be overriden in php-fpm's pool configuration.
If you are using apache+mod_php ini values may be overriden in .htaccess file.
Check that, before resolving to error_reporting(0), turning off error_reporting completely is not what you should do, as this may lead to broken logic (many popular libraries and frameworks rely on error reporting by setting handlers to traslate errors to exceptions).
In terms of portability use of error suppressing operator is preferred, dispite its affect on performance.

Errors hidden with # in php

I am repairing some old code that was made before me and I took about 2 hours to find a error because it was hidden by #.
Is that a way to deactivate this in PHP?
display_errors don't get errors hidden by #
You can define a custom error handler as described in the php documentation for error control operator
You can enable track_errors to save whatever error was generated by the error control operator (#) to a PHP variable. You can set track_errors in your php.ini file or use ini_set.
If the track_errors feature is enabled, any error message generated by
the expression will be saved in the variable $php_errormsg. This
variable will be overwritten on each error, so check early if you want
to use it.
Example
<?php
ini_set('track_errors', true);
#strpos();
echo $php_errormsg;
Will output:
strpos() expects at least 2 parameters, 0 given
Caveats
It is important to note that critical errors that cause the script to terminate that are suppressed by # will not be discoverable this way. In this case, if your script dies unexpectedly and without an error message, that should be a good indication to search for the # in your code.
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.

Suppress an error from the logs too

CodeIgniter 2.x still uses the classic mysql. We all know it's bad practice to still use it, but my job still requires me to use CodeIgniter.
I always have my Console.app (OSX) open watching my Apache/MySQL/PHP/CodeIgniter-native error logs.
Now I mostly have all notices/errors/etc. fixed always instantly when I see them and constantly monitor my development with Webgrind on my MAMP.
Back to the start; I constantly have one big annoying thing each page-load PHP always gives the error about mysql_pconnect is going to get deprecated in the future.
In the CodeIgniter driver the command is suppressed by # to not print the warnings to the screen, but it still ends up in my logs.
Is there any viable way to except one such error specifically in either PHP code or the PHP settings?
Locally I could recompile the whole PHP core and just remove the warning, but I would like to have the logs on our production installations rid of those warnings too :P.
Thanks in advance!
Traditionally, you can use set error verbosity using error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED) (i.e., report everything—except notices and deprecation warnings) as mentioned in "disabling deprecated errors".
Your issue may be related to CodeIgniter taking ownership of all errors.
system/core/CodeIgniter.php calls the function set_error_handler. You can find and modify the function _exception_handler it invokes on error in system/core/Common.php. It doesn't appear to be a configurable, so you may simply want to edit the line that begins with $is_error.

Detecting error-control operator

Please tell me if this is correct. In my error handler, I need to be able to detect when the # error-control operator was used to suppress errors, because some external libraries (sadly) use it a lot. Execution of the script should continue, just like when you don't use custom error handlers.
When the at-sign is used, PHP temporarily sets error_reporting to 0. So at the start of a script we set error_reporting to any value but zero - we can now do some beautiful IF/ELSE magic. To avoid any errors being shown at the frontend, we also set display_errors to 0, this will override error_reporting (but we can still use it's value for magic).
<?php
ini_set('display_errors',0);
error_reporting(E_ALL);
function error_handler($errno, $errstr, $errfile, $errline)
{
if (error_reporting()===0) return;
else die();
}
set_error_handler('error_handler');
//This issues an error, but the handler will return and execution continues.
//Remove the at-sign and the script will die()
#file();
echo 'Execution continued, hooray.';
?>
So.. Are there no catches here? Except the one where the external library overrides my error handling.. (any tips on that?)
Considering what your script does, and some user notes on the # operator manual page, it seems what you are doing is OK.
For instance, taras says :
I was confused as to what the # symbol
actually does, and after a few
experiments have concluded the
following:
the error handler that is set gets called regardless of what level the
error reporting is set on, or whether
the statement is preceeded with #
it is up to the error handler to impart some meaning on the different
error levels. You could make your
custom error handler echo all errors,
even if error reporting is set to
NONE.
so what does the # operator do? It temporarily sets the error reporting
level to 0 for that line. If that line
triggers an error, the error handler
will still be called, but it will be
called with an error level of 0
And the set_error_handler manual page seems to confirm that :
Of particular note is that this value will be 0 if the statement
that caused the error was prepended by the # error-control operator.
Here too, there are some user notes that can be useful ; for instance, this one (see the begining of the code)
Still, if what you want is to "disable" the effect of the # operator (not sure I understood the question correctly ; this might help you anyway), to be able to get the error messages while you are on your development environment, you can install the scream extension (pecl, manual)
Provided you configure it the right way, setting this in your php.ini (after installating/loading the extension, of course) :
scream.enabled = 1
This extension will simply disable the # operator.
And here's an example (quoting the manual) :
<?php
// Make sure errors will be shown
ini_set('display_errors', true);
error_reporting(E_ALL);
// Disable scream - this is the default and produce an error
ini_set('scream.enabled', false);
echo "Opening http://example.com/not-existing-file\n";
#fopen('http://example.com/not-existing-file', 'r');
// Now enable scream and try again
ini_set('scream.enabled', true);
echo "Opening http://example.com/not-existing-file\n";
#fopen('http://example.com/another-not-existing-file', 'r');
?>
And this will output :
Opening http://example.com/not-existing-file
Opening http://example.com/not-existing-file
Warning: fopen(http://example.com/another-not-existing-file): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in example.php on line 14
I am not sure I would use this extension on a production server (where I never want errors displayed), but it is very useful on a development machine, when using old code, on an application/library that uses # operator extensivly...

Categories