I'm new on the site (hi!) and I had a problem that I can't resolve yet. I look for it, but no results... I think it's a stupid thing, but I can't find the solution.
I'm migrating a system (PHP) to other server (both are CentOS) and I have a problem with the quotes in PHP variables:
Example:
--------
$_GET[var]
$db_reg[assoc]
$array[value]
define(NAME,'value')
etc..
All cases can fix adding quotes to indexes, but I have thousand of PHP files, with millions of lines each one, and I can't check one by one... it will take around two lives and a half.
In the old server, it works normally, but in the new, the variables are not recognized, shows a PHP notice:
"Notice: Use of undefined constant XXXX - assumed 'XXXX in..."
(ej: $_POST[XXXX])
Is there a configuration in Apache or PHP for recognizing or not (indistinct) quotes on variables?
The PHP version on both servers are the same, and I have checked the php.ini file, and they are similar.
I guess you need some information about variables and their usage (when working with arrays) and fixed index concretions.
Usage of variables:
$array = array('hi', 'you', 'there');
$i = 1;
echo $array[$i]; // -> Works and is **fine** (will output 'you')
// --------------------------------
$array = array('a' => 'hi', 'b' => 'you', 'c' => 'there');
echo $array['a']; // -> Works and is **fine**
// Note: in especially that case **NEVER** use barewords like this: echo $array[a] for >> a << here is expected to be a constant which (mostly) does not exist!
// PHP is so fuzzy that it will mostly interpret around like insane and output you the desired value ('hi' in that case), but that was never meant to be! And should always be prevented. That's the reason for you getting that notice...
// So never do this:
echo $array[a];
// ... if >> a << is NOT a valid and available constant
Important (summed up to the point):
Words without quotes and the dollar are considered constants which you perhaps do not use very often. In most cases, you use quotes (like described above) or real variables (identified by $) as index to access data structures/arrays.
Well, you can try editing the php.ini file:
Change
error_reporting=E_ALL
to
error_reporting = E_ALL & ~E_NOTICE
This will disable all notices, but I am not sure sure if this will get your issue resolved. Please try and let us know if this is working or not for you.
Related
I'm trying to make the client's legacy PHP application to work for PHP 5.3. I see this kind of code a lot:
$SETTINGS[cart][picsize] = "100";
$settings[user][time] = 123;
1) Are variables case-insensitive in PHP? Is $SETTINGS same as $settings?
2) I'm getting 'undefined constant' for the cart, picsize, etc. and they don't seem to be defined anywhere in the codebase. Did some older versions of PHP allow referencing array indices without quotes, or what is going on here?
Variables are case sensitive, functions and classes are not.
It could have been that your PHP configuration had a certain level of error reporting turned off and you never saw the error. It might have worked for you because those undefined constants will get turned into strings. (credit: #watcher). You should always reference associate array indexes with quotes, unless they are not a string. Strings should always be quoted, unless you have defined a constant. You do not have to quote integers, double or bool.
$SETTINGS["cart"]["picsize"] = 100;
$settings[user][time] = 123;
Those two statements are completely different and are in no way related as far as variables are concerned. Regardless if there only difference is upper case and lower case. They are still not the same.
So.. I'm still confused by this, when creating an array with $array = array(); and then manually setting variables like:
<?php
$array[] = 1;
$array['type'] = 2;
$array['number'] = 3;
I know, this is OK for PHP to do, but then when I echo something like $array['none'] it won't show a E_NOTICE for undefined variables.
Can someone explain me, why?
It will. If you have turned on error reporting, it should display a warning similar to the one below:
Notice: Undefined index: none in /path/to/script.php line X.
To check, try the following:
<?php
ini_set('display_errors',1);
error_reporting(E_ALL);
$array = array();
echo $array['none'];
And, if you want to actually make sure they exist before trying to use them in your code, use isset():
if(isset($array['none'])) {
// do stuff ...
}
See it live!
All this is explained on the config doc page, too:
Enabling E_NOTICE during development has some benefits.
For debugging purposes: NOTICE messages will warn you about possible bugs in your code. For example, use of unassigned values is warned. It is extremely useful to find typos and to save time for debugging.
NOTICE messages will warn you about bad style. For example, $arr[item] is better to be written as $arr['item'] since PHP tries to treat "item" as constant. If it is not a constant, PHP assumes it is a string index for the array.
It's quite simple: When you access a key that doesn't exist, and assign it a new value, PHP will create that key, and add it to the list (or array). But when you try to access a non-existing key, and attempt to echo it's value, PHP won't crash, but it'll let you know that your code contains a possible bug:
$arr = array('foo' => 'bar');
echo $arr['fo'];
This issues a notice because my code may contain a typo. I may expect the key fo to exist, while clearly it doesn't, so I need to work on my code some more.
Another reason why this notice is issued is because lookups for non existing properties/keys are "slow". In order for PHP to know for a fact that the key doesn't exist, the entire array has to be scanned. That, too, is not ideal, though inevitable at times. If you have code that issues tons of E_NOTICE's, chances are that some simple if's, like:
if (!isset($arr['fo']))
{
$arr['fo'] = '';
}
echo $arr['fo'];
Will, though adding more code, effectively speed up your code. Not in the least because issueing notices isn't free (it's not that expensive, but not free either).
Other benefits:
Notices also let you know when you forgot to quote array keys, for example
echo $arr[foo];
echo $arr['foo'];
Initially, both will echo bar, but let's add 1 line of code to this:
define('foo', 'bar');
echo $arr[foo];
echo $arr['foo'];
This won't, because foo is now a constant, so $arr[foo] amounts to $arr['bar'];, which is an undefined index. Turning off notices, will just echo the string representation of NULL, which is an empty string.
Basically, notices help you. Use them, listen to them, and fix them. If your site is broken, fix it. If you get into the habbit of ignoring these notices, you'll probably set your ini files to a more "forgiving" setting, and grow lazy.
As time progresses, your code will become ever more messy/smelly, until such time you actually have a difficult to trace bug. You'll decide to turn your error reporting to E_STRICT | E_ALL, and won't be able to see the actual notice/warning that points out where your bug actually is, because your screen will be cluttered with E_NOTICE undefined index/variable...
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.
So I came across this feature/bug today and I'm struggling to wrap my head around what is going on.
so we all know that in php this:
echo 'hello';
print 'world';
echo gettype('test');
will return this:
hello
world
string
However, until today I was unaware that this:
echo hello;
print world;
echo gettype(hello);
will return this:
hello
world
string
What is going on here? What is happening in php's compilation process that it sees any single word as a string? Does this have a name? Does it have any utility?
If PHP can't find a function or constant by the name of hello, then yes, it treats it as a string. However, this is bad practice, and is even warned against:
>php -r 'error_reporting(E_ALL|E_STRICT);echo gettype(blah);'
PHP Notice: Use of undefined constant blah - assumed 'blah' in Command line code on line 1
So, the moral of the story is to always turn on error_reporting in PHP (just like you should always use strict and use warnings in Perl).
If you are not wrapping a piece of "string" inside quotes (be it double or single), the interpreter will try to make a guess and cast that into a String. I believe when you run that piece of PHP in error_reporting(E_ALL) you will see a notice
Notice: Use of undefined constant string - assumed 'string' in Command line code on line 1
A good practice is to always turn on error_reporting to E_ALL in development setups, but remember to turn it to less descriptive in production, you don't want people to have access to sensitive information (such as path) if your php errors out.
I have working code I developed for a linux server that when I have tested locally using WAMP have started to get strange Xdebug errors of the form
Notice: Use of undefined constant fullName - assumed 'fullName'
The code is...
$allVars = array(
fullName=>$fullName,
telephone=>$telephone,
email=>$email,
fAddr=>$fAddr,
tAddr=>$tAddr,
sngRtnSelect=>$sngRtnSelect,
oDate=>$oDate,
rDate=>$rDate,
tAdditional=>$tAdditional,
noPassengers=>$noPassangers,
vehicleType=>$vehicleType,
distance=>$distance,
priceTot=>$finalPrice
);
I thought the above was a straight forward array definition. Could anyone shed light on why such errors are appearing on WAMP and not the linux server?
If I have missed something obvious, then my apologies, however this is the identical code that worked on the linux/apache server. Thanks.
If you are defining a string key then you should put it inside quotes. Like this:
$arr = array ( 'some_key' => 'some_value' )
However, when you are working with integers you should not use quotes, otherwise you'll create a string.
$arry = array ( '0' => 'this is a string key because it has quotes around.',
0 => 'this is an integer key because it has not quotes around.');
By the way, when you do not use quotes for a string value, it means that you refer to a defined variable.
define ( 'name', 'Savas Vedova' );
echo name; // this will print Savas Vedova to the screen.
$allVars = array(
'fullName'=>$fullName,
'telephone'=>$telephone,
'email'=>$email
);
you should use ' <= this ;)
Both right, use quotes. Also, that is NOT an error but a Notice. Surely you have a php.ini with error_reporting including E_NOTICE, so the notices show up (in the end, PHP interpreter assumed the right thing, even if you did it wrong!) [but please, please, do it right, don't be lazy!!! :P]
http://php.net/manual/en/function.error-reporting.php
perhaps, WAMP default is less forgiving than linux default
To directly answer your question...
Could anyone shed light on why such errors are appearing on WAMP and not the linux server?
Your servers have different levels of error reporting defined in their configuration files.
The message in question is an E_NOTICE level error.
See http://php.net/manual/en/errorfunc.configuration.php