Alright, PHP is throwing this error (in the log) and it's quite detrimental to the application.
PHP Notice: Undefined index: sessid in methods.php on line 7
Yes, I'm aware of what this error means, what I cannot figure out is why it's obviously defined and saying it's undefined. Here is the relevant code in methods.php
$sessid = mysql_real_escape_string($_REQUEST['sessid']);
Now before you go off and say that "NO IT'S UNDEFINED!!!", here is the POST request to the methods.php (and yes, I'm also aware that $_REQUEST "can't be trusted").
method=r&room=general&sessid=d0sma94yw4r4cdckv2ufhb&qid=1276957562382
As you can see, the sessid is obviously defined and is being sent off to the methods.php. I just thought I'd throw in the relevant query here too.
mysql_query('UPDATE active SET time=\''.$timestamp.'\' WHERE sessid=\''.$sessid.'\'');
Yes, time is also defined as:
$time = time();
So, what is the issue here?
Barring typos etc, if you have a version >= 5.3.0, you might want to check what request_order (or variables_order if request_order is empty) ini-setting is set to. If in none of those two the 'P' is set, the $_POST array will not be in $_REQUEST (and not even set it the 'P' is not in variables_order afaik). See: http://www.php.net/manual/en/ini.core.php#ini.request-order
If those 2 are allright, I'd say you have a logical error somewhere else, var_dump() the $_POST and $_REQUEST superglobals to check.
Related
While my site was working without any problem I suddenly started to have a really high CPU usage on my server so I started to check the code more carefully and enabled E_ALL error reporting.
Then I found out I had a great many of this "notices":
Notice: Undefined index: userID in /var/www/vhosts/mydomain.com/httpdocs/header.php on line 8
Most or them refer to unset cookies, for example this:
$uid = $_COOKIE['userID'];
If the user is unlogged I get a notice right there, and every time I use $uid.
What I want to know if this: Are this notices harmless or can they really cause any problems in my site? (Speed issues, errors etc.)
It is a notice only, try this code:
$uid = isset($_COOKIE['userID']) ? $_COOKIE['userID'] : 0;
It is not hamless (depending on the point of view), and you can disable this with error reporting functions, otherwise, the correct way is verify if index exists isset($_COOKIE['userID']) and if not, define a default value (null for instance)
$var = isset($foo) ? $foo : 'default';
You need to verify if variable exists, if you don't known it exists or not.
$var = 'foo'
if($var == 'foo') { // I known $var is defined, because I have defined it.
[..]
}
/**
* Above, I don't known if user go to mywebsite.com/index.php or
* mywebsite.com/index.php?foo=bar, so, I need to verify if index is defined
*/
if(isset($_GET['foo']) && $_GET['foo'] == 'bar') {
[...]
}
Those notices will cause a little bit of a speed problem, because raising a notice costs some extra effort.
The main problem though is that this is a serious error. You are trying to work with something that doesn't exist. This may or may not lead to Bad Things Happening, but it means your program is not correct. Since you should always develop with error reporting on full power to see and solve actual problems, notices about undefined indexes or undefined variables are serious and need to be solved. Anything that PHP complains about is serious and needs to be solved. See The Definitive Guide To PHP's isset And empty.
Notices are in general harmless, yet they may indicate a poor application design. In general it is always a good idea to utilize available PHP tools (i.e isset($someVar)) to make sure that your business logic is taking proper care of variable initialization. When you see no such notices with E_ALL error reporting setting, it's always better.
The Notice warning is in the first point of view harmless, but you should keep in mind, that the programming is not right and it might be causes errors on following lines.
In your example it es better to use
$uid = isset($_COOKIE['userID'])?$_COOKIE['userID']:0;
So you can be sure, that $uid always has a value and when the value greater then 0 you have a falid userId ...
I want to use a global variable setup where they are all declared, initialized and use friendly syntax in PHP so I came up with this idea:
<?
error_reporting(E_ERROR | E_WARNING | E_PARSE | E_NOTICE);
$GLOBALS['debugger'] = 1; // set $GLOBALS['debugger'] to 1
DEFINE('DEBUGGER','$GLOBALS["debugger"]'); // friendly access to it globally
echo "1:" . DEBUGGER . ":<br>";
echo "2:" . ${DEBUGGER}. ":<br>";
echo "3:" . $GLOBALS['debugger'] . ":<br>";
if (DEBUGGER==1) {echo "DEBUG SET";}
?>
generates the following:
1:$GLOBALS["debugger"]:
Notice: Undefined variable: $GLOBALS["debugger"] in /home/tra50118/public_html/php/test.php on line 8
2::
3:1:
How can there be an error with 2: when clearly $GLOBALS["debugger"] IS defined? And then not generate a similar notice with the test at line 10?
I think what I am trying to do is to force PHP to interpret a string ($GLOBALS["debugger"]) as a variable at run time i.e. a constant variable variable
Disclaimer: I agree with the comments, globals are generally a bad idea.
That said, there's a few questions here that are worth answering, and the concept of indirection is useful, so here goes.
${'$GLOBALS["debugger"]'} is undefined. You don't include the leading '$' when using indirection. So, the correct version would be define('DEBUGGER', 'GLOBALS["debugger"]').
But, this doesn't work either. You can only access one level down via indirection. So you can access the array $GLOBALS, but you can't access keys in that array. Hence, you might use :
define('DEBUGGER', 'debugger');
${DEBUGGER};
This isn't useful, practically. You may as well just use $debugger directly, as it's been defined as a global and will be available everywhere. You may need to define global $debugger; at the start of functions however.
The reason your if statement is not causing notices is because you defined DEBUGGER to be a string. Since you aren't trying to use indirection in that line at all, it ends up reading as:
if ("$GLOBALS['debugger']"==1) {echo "DEBUG SET";}
This is clearly never true, though it is entirely valid PHP code.
I think you may have your constants crossed a bit.
DEFINE('DEBUGGER','$GLOBALS["debugger"]'); sets the constant DEBUGGER to the string $GLOBALS["debugger"].
Note that this is neither the value nor the reference, just a string.
Which causes these results:
1: Output the string $GLOBALS["debugger"]
2: Output the value of the variable named $GLOBALS["debugger"]. Note that this is the variable named "$GLOBALS["debugger"]", not the value of the key "debugger" in the array $GLOBALS. Thus a warning occurs, since that variable is undefined.
3: Output the actual value of $GLOBALS["debugger"]
Hopefully that all makes sense.
OK, thanks to all who answered. I think I get it now, I am new to PHP having come form a C++ background and was treating the define like the C++ #define and assuming it just did a string replace in the precompile/run phase.
In precis, I just wanted to use something like
DEBUGGER = 1;
instead of
$GLOBALS['debugger'] = 1;
for a whole lot of legitimate reasons; not the least of which is preventing simple typos stuffing you up. Alas, it appears this is not doable in PHP.
Thanks for the help, appreciated.
You can not use "variable variables" with any of the superglobal arrays, of which $GLOBALS is one, if you intend to do so inside an array or method. To get the behavior you would have to use $$, but this will not work as I mentioned.
Constants in php are already global, so I don't know what this would buy you from your example, or what you are going for.
Your last comparison "works" because you are setting the constant to a string, and it is possible with PHP's typecasting to compare a string to an integer. Of course it evaluates to false, which might be surprising to you, since you expected it to actually work.
If I use an if statement like,
<?php if(strlen($variable) >=3) { ... } ?>
and the variable isn't actually set, this would bring me an error in PHP 5(3.6). But if I use isset() and strlen(), it would not. However, in PHP 4(4.9), when I use only strlen(), it comes through completely fine, without any errors.
Is this something that has changed since version 4.4.9? If not, is there a way I can bring back the old fashioned way of checking variables in php.ini? I find it really strange that you'd have to run both of these functions on a variable, as it really makes the code more messy than necessary. Especially if you're working with ternary operators...
To be exact, I'm working on a GET variable, and I'm getting these kind of errors:
Undefined index: x in file.php on line x
Although I agree with #deceze's comment, the reason you are seeing these messages, is not a difference between php 4 and php 5 but a difference in your error reporting settings. Now you are showing E_NOTICE and before you were not.
Consider the following snippets of code:
Exhibit A:
$_REQUEST = json_decode(stripslashes(json_encode($_REQUEST, JSON_HEX_APOS)), true);
Exhibit B:
${'_REQUEST'} = json_decode(stripslashes(json_encode(${'_REQUEST'}, JSON_HEX_APOS)), true);
Exhibit C:
${'_' . 'REQUEST'} = json_decode(stripslashes(json_encode(${'_' . 'REQUEST'}, JSON_HEX_APOS)), true);
Both exhibit A and B work perfectly fine, exhibit C however displays a very strange error message:
Notice: Undefined variable: _REQUEST
What makes it even more weird is that this only happens with the $_REQUEST superglobal, if I try it with $_GET, $_POST or $_COOKIE all experiments work fine without raising error notices.
I'm guessing this is a PHP bug? I'm running on PHP 5.3.0.
(I tested with PHP 5.3.1)
One funny thing is that this portion of code :
<?php
var_dump(${'_' . 'REQUEST'});
Gets the notice Undefined variable: _REQUEST
But this one :
<?php
var_dump($_REQUEST);
var_dump(${'_' . 'REQUEST'});
Doesn't give any notice, and shows two empty arrays.
For a while, I though this could be related to auto_globals_jit, but $_REQUEST doesn't seem to the concerned by that directive... But there is one interested thing said, here :
Usage of SERVER and ENV variables is
checked during the compile time so
using them through e.g. variable
variables will not cause their
initialization.
Maybe, after all, even if it's not said in the manual, auto_globals_jit has an impact on $_REQUEST...
And, to be sure, I turned Off auto_globals_jit in my php.ini file :
; When enabled, the SERVER and ENV variables are created when they're first
; used (Just In Time) instead of when the script starts. If these variables
; are not used within a script, having this directive on will result in a
; performance gain. The PHP directives register_globals, register_long_arrays,
; and register_argc_argv must be disabled for this directive to have any affect.
; http://www.php.net/manual/en/ini.core.php#ini.auto-globals-jit
auto_globals_jit = Off
And tried this code again :
<?php
var_dump(${'_' . 'REQUEST'});
And I now get an empty array, and not a notice anymore.
So it seems auto_globals_jit does indeed have an impact on $_REQUEST -- even if it's not mentionned in the manual.
Please note that variable variables cannot be used with PHP's Superglobal arrays within functions or class methods. The variable $this is also a special variable that cannot be referenced dynamically.
http://www.php.net/manual/en/language.variables.variable.php
This is most likely related to:
Usage of SERVER and ENV variables is checked during the compile time so using them through e.g. variable variables will not cause their initialization.
From Pascal's Answer.
Which can all be related back to the auto_globals_jit option.
I'm going with the bug since $_GET etc do work
It's not been mentioned at the php bugtrack: http://bugs.php.net/
Maybe you should report it.
I did some quick debugging in Zend Studio:
<?php
var_dump( ${'_' . 'REQUEST'});
var_dump( ${'_REQUEST'});
var_dump( $_REQUEST);
And it seemed to work with the included PHP 5.2.10. Maybe you could use this as a workaround:
$foo = '_' . 'REQUEST'
$$foo //<-- is the same as $_REQUEST
EDIT: Woops, this wouldn't work with Superglobals, sorry -- thanks Cacha102
Found this "bug" report. According to tony2001#php it's not a bug:
Variable variables: Superglobals
cannot be used as variable variables
inside functions or class methods.
This page says the same thing, but what is weird is that this only happens with $_REQUEST, other GPC superglobals don't raise the error notice, can anyone double-check this?
I trying to understand if a isset is required during form processing when i check $_REQUEST["input_name"] if no value is passed it doesn't cry about it and php doesn't throw out an error if you are trying to access a array item which doesn't exist....i can use if($_REQUEST["input_name"])..
what about "empty" even in those cases i can use if()
THnks
I wouldn't recommend using the $_REQUEST superglobal for capturing form input, unless you're testing a form. Use $_GET or $_POST instead, unless you have a really good reason.
Also, isset() and array_key_exists() both do the same trick with regard to array keys, although array_key_exists() is clearer in an arrays context.
I recommend using:
error_reporting(E_ALL); //E_ALL - All errors and warnings
within your development environment, as that can expose where better practices might be applied, such failure to declare variables before they are used, etc.
There are different type of error levels. Checking a variable that is not set only throws a notice. Your error reporting is probably set to ignore those. It is best practice to always use isset when you want to check if a variable has been set, although it does have its gotchas.
Doing only what you are doing above, for example, if $_REQUEST["input_name"] is the string "0", it will evaluate to false. Also it is not a good idea to use $_REQUEST to begin with, as it can be affected by stuff like cookies and such and it's usually a code smell for bad architecture.
using $_REQUEST is pretty much a hack. You should be using $_POST or $_GET (depending on what you are doing) and you should use isset().
Every book I've read on PHP seems to say that.
Generally, at least for testing, set error reporting to E_ALL (all errors and warnings) either in your php.ini or in code using error_reporting(E_ALL); (Look into adding E_STRICT too.) Better to get an obvious notice about an error up front, than to have something subtle go wrong that you don't catch till later.
Avoid using $_REQUEST, which is too vague (it includes GET, POST AND cookie values), and use the $_POST or $_GET if those are what you really mean, and do check with isset($_POST["input_name"])
The short answer is "Yes." :)
if($_REQUEST["input_name"])
will throw a notice (error) if "input_name" doesn't exist, so isset() is recommended.