This gives the classical warning (that in next version will be an error):
$var[$otherVar[someIndex]] = $myValue;
This does not:
$var["$otherVar[someIndex]"] = $myValue;
Both works the same.
Shouldn't PHP 7.2 warn in both cases?
In case it does not, what is the justification to allow the second one, with the new rules PHP new versions tries to impose?
String interpolation doesn't require that the key be quoted, because the key is already a string. It won't be interpreted as a constant (which is the point of the message you get from your first example), and there's no chance that you meant to get $otherVar[someIndex()], because that wouldn't even work as intended in this context. So the problems with barewords simply don't apply.
You will get a message if you tried to say $var["{$otherVar[someIndex]}"]. Variables interpolated that way work more like you expect, and someIndex will again be interpreted as a constant.
Related
I work on a website that, since last Oct, has had the following lines of code that work just fine:
if(empty($post_types))
{
$post_types[] = 'post';
$post_types[] = 'product-list';
}
I had not seen this construct in PHP before, (and since I started my programming work in C, it's a little irritating), but it works.
We started a second site with the same technology and basic setup that threw the following error at the same lines of code,
"Uncaught Error: [] operator not supported for strings ..."
The sites are hosted at the same place, but I noticed that they are using different 7.x versions of PHP. I did a bit of research to see if the behavior is due to a change in PHP 7.3, but I didn't find an answer.
Please note that my question is on whether this situation is possibly a PHP version issue, not how to solve the array problem, which I changed with
$post_types = array('post', 'product-list');
I found your answer in the PHP docs Creating/modifying with square bracket syntax:
$arr[key] = value;
$arr[] = value;
// key may be an integer or string
// value may be any value of any type
If $arr doesn't exist yet, it will be created, so this is also an
alternative way to create an array. This practice is however
discouraged because if $arr already contains some value (e.g. string
from request variable) then this value will stay in the place and []
may actually stand for string access operator. It is always better to
initialize a variable by a direct assignment.
Note: As of PHP 7.1.0, applying the empty index operator on a string throws a fatal error. Formerly, the string was silently converted to
an array.
So it appears there is a change in PHP 7.1.0 matching with the problem you described.
In your code, your $post_type variable must be initialized as a string [EDIT : I could only reproduce the problem with an empty string], and was previously ( PHP < 7.1.0) silently converted to an array.
I'm using PHP 7.0.2
Consider below text from the PHP Manual :
Why is $foo[bar] wrong?
Always use quotes around a string literal array index. For example,
$foo['bar'] is correct, while $foo[bar] is not. But why? It is common
to encounter this kind of syntax in old scripts:
<?php
$foo[bar] = 'enemy';
echo $foo[bar];
// etc
?>
This is wrong, but it works. The reason is that this code has an
undefined constant (bar) rather than a string ('bar' - notice the
quotes). It works because PHP automatically converts a bare string (an
unquoted string which does not correspond to any known symbol) into a
string which contains the bare string. For instance, if there is no
defined constant named bar, then PHP will substitute in the string
'bar' and use that.
From the above text I'm not clear that when PHP encountered bar() which does not correspond to any known symbol i.e. undefined constant what PHP actually does with it?
How can PHP convert a bare string bar into a string which contains the bare string i.e. 'bar'?
Is PHP defining a constant titled bar and assigning a string value 'bar' to it?
Like bar = 'bar';
If yes, can I make use of the constant bar somewhere in the further code?
Because in PHP only a variable and a constant can contain value/hold the value and not type like string contain/hold any value.
From the above text I'm not clear that when PHP encountered bar() which does not correspond to any known symbol i.e. undefined constant what PHP actually does with it?
The warning associated with this behavior says it all, really:
Warning: Use of undefined constant bar - assumed 'bar' (this will throw an Error in a future version of PHP)
The bare word is treated as a string, not as a constant -- it's treated exactly as if you'd written 'bar'. The expression defined('bar') will still be false, other instances of bar in your code will also throw warnings, and code which depends on this behavior will stop working entirely in future versions of PHP.
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.
Is it okay to use array without single or double quotion like $array[key]? I thought it is bad because PHP look for constant first if I don't use single or double quotation. One of my colleagues told me that it does not matter.
What do you guys think?
It is not considered as OK -- even if it will work in most cases.
Basically, when PHP sees this :
echo $array[key];
It will search for a constant, defined with define, called key -- and, if there is none, if will take the 'key' value.
But, if there is something like this earlier in your code :
define('key', 'glop');
It will not take
echo $array['key'];
anymore ; instead, it'll use the value of the key constant -- and your code will be the same as :
echo $array['glop'];
In the end, not putting quotes arround the key's name is bad for at least two reasons :
There is a risk that it will not do what you expect -- which is very bad
It might, today...
But what about next week / month / year ?
Maybe, one day, you'll define a constant with the wrong name ;-)
It's not good for performance :
it has to search for a constant, before using 'key'
And, as said in a comment, it generates notices (even if you disable error_reporting and display_errors, the notices/warnings/errors are still generated, even if discarded later)
So : you should not listen to that guy on this point : he is wrong : it does matter.
And if you need some "proof" that's "better" than what people can tell you on stackoverflow, you can point him to this section of the manual, as a reference : Why is $foo[bar] wrong?
This is not okay and to add to what others have said, it will trigger an error in most cases:
8 Notice Use of undefined constant key - assumed 'key' in file: 'index.php' on line 46
See the section in the PHP Manual for "Why is $foo[bar] wrong?" under "Array do's and don'ts" on this page: http://php.net/manual/en/language.types.array.php
This is wrong and will auto-define a constant:
$var = $array[bar];
This usage however is correct:
$var = "string $array[bar] ...";
For compatibility with PHP2 this old syntax is still allowed in string context. Quoting the key would lead to a parse error, unless you also use { curly braces } around it.
From the PHP Manual - Why is $foo[bar] wrong?
Always use quotes around a string literal array index. For example, $foo['bar'] is correct, while $foo[bar] is not. But why? It is common to encounter this kind of syntax in old scripts:
<?php
$foo[bar] = 'enemy';
echo $foo[bar];
// etc
?>
This is wrong, but it works. The reason is that this code has an undefined constant (bar) rather than a string ('bar' - notice the quotes). PHP may in future define constants which, unfortunately for such code, have the same name. It works because PHP automatically converts a bare string (an unquoted string which does not correspond to any known symbol) into a string which contains the bare string. For instance, if there is no defined constant named bar, then PHP will substitute in the string 'bar' and use that.
There is some more examples in the manual for you to check out.
Unless the key actually is a constant, there is no reason for you not to be putting quotes around the key.
The way PHP works is it looks for the constant value of what you've put, but it takes the string representation of it if the constant cannot be found.
If someone were to edit your code down the road and add a constant with that key name, it would just cause more headaches.
It's bad practice to not quote key values, for a number of reasons:
Potential collisions with meaningful symbol names, such as define'd constants.
Some keys can't be expressed without quoting (for instance, the key "]").
Bad habits can bite you later on (namely in regards to #1 and #2).
Performance - searching for define's takes time.
If you're wanting to avoid typing quotes around names that are just standard elements of a thing you're passing around a lot, perhaps you might want to use objects instead, which take a object->property syntax instead of an $array["element"] syntax.
I haven't made any changes to the code affecting the COOKIE's and now I get the following:
Use of undefined constant COOKIE_LOGIN - assumed 'COOKIE_LOGIN'
//Destroy Cookie
if (isset($_COOKIE[COOKIE_LOGIN]) && !empty($_COOKIE[COOKIE_LOGIN]))
setcookie(COOKIE_LOGIN,$objUserSerialized,time() - 86400 );
I'm not sure what I need to do to actually change this since I do not know what chnaged to begin with and so cannot track the problem.
Thanks.
You need to surround the array key by quotes:
if (isset($_COOKIE['COOKIE_LOGIN']) && !empty($_COOKIE['COOKIE_LOGIN']))
setcookie('COOKIE_LOGIN',$objUserSerialized,time() - 86400 );
PHP converts unknown literals to strings and throws a warning. Your php.ini probably had the error reporting level to not display warnings but someone may have updated it or something. In either case, it is bad practice to take advantange of PHP's behavior in this case.
For more information, check out the php documentation:
Always use quotes around a string literal array index. For example, $foo['bar'] is correct, while $foo[bar] is not.
This is wrong, but it works. The reason is that this code has an undefined constant (bar) rather than a string ('bar' - notice the quotes). PHP may in future define constants which, unfortunately for such code, have the same name. It works because PHP automatically converts a bare string (an unquoted string which does not correspond to any known symbol) into a string which contains the bare string. For instance, if there is no defined constant named bar, then PHP will substitute in the string 'bar' and use that.
You can't say $_COOKIE[COOKIE_LOGIN] without error unless COOKIE_LOGIN is an actual constant that you have defined, e.g.:
define("COOKIE_LOGIN", 5);
Some people have habits where they will write code like:
$ary[example] = 5;
echo $ary[example];
Assuming that "example" (as a string) will be the array key. PHP has in the past excused this behavior, if you disable error reporting. It's wrong, though. You should be using $_COOKIE["COOKIE_LOGIN"] unless you have explicitly defined COOKIE_LOGIN as a constant.