I knocked to a phenomenon in an existing php source,
with field access without apostrophe like this: $_GET[test].
I got unsure, also don't know, that this is a possible way,
so I wrote a short example for testing:
echo "Array Test, fields without apostrophe, like \$_GET[fieldname]<BR><BR>";
$a = array();
$a['test'] = "ArrayValue";
echo "case 1 -> \$a['test']: " . $a['test'] . "<BR>";
echo "case 2 -> \$a[\"test\"]: " . $a["test"] . "<BR>";
echo "case 3 -> \$a[test]: " . $a[test] . "<BR>";
And it works, every result got the value (ArrayValue).
I prefer the access method like case 2.
Is case 3 a normal, allowed coding style in php?
What happens here, is that PHP sees a constant called test. If the constant is defined, the value is returned, it isn't defined, PHP falls back to the string "test". For example:
$array = array("A" => "Foo", "B" => "Bar", "C" => "Baz")
define("B", "C");
echo $array[A]; // The constant "A" is undefined,
// so PHP falls back to the string "A",
// which has the value "Foo".
echo $array["B"]; // The result is "Bar".
echo $array[B]; // The value of constant "B" is the string "C".
// The result is "Baz".
It's for backwards compatibility and you should never use it. If you'll turn on notices, you'll see that PHP complains about it.
If you don't put the key into quotes, it will be handled as an undefined constant (assuming it is not defined anywhere), which may work for now, but can fail in future PHP versions. Therefor it is just wrong and the PHP documentation states this variant also as wrong. Check out 'Arrays do's and don'ts'.
By the way: If you put the key into double quotes, it renders variables inside to the key-name.
Using array key names without quotes is a legacy feature in PHP. It was originally the way to do it, but it is no longer recommended and is only still supported for backward compatibility. It will throw a warning message if you have strict mode enabled.
The reason it works is that it sees the key name in this form as a constant. When PHP sees an unknown constant, it defaults to the name of the constant as the value, hence it works as a string replacement.
It would break if you had define() elsewhere in your program that set the value of that constant. It also doesn't work if your key name contains spaces, starts with a digit, or is an invalid constant name for any other reason.
For these reasons, it is not recommended to use this method.
But most of all, the PHP developers have stated publicly that it is not good practice, which may well mean that future PHP versions remove the ability to write code like this.
Related
I'm currently programming a website (in PHP4). I plan to save values, which do not change during runtime, in constants. Those are for example the version number of login-data for the database.
Question 1: are there any (security relevant) problems that can arise from saving data in constants?
At the moment I do the following to define and call the constant:
define("VERSION", "1.0");
echo "Current version: ".VERSION."."; // Result: "Current version: 1.0."
There is one thing that annoys me: In case a constant is not defined, the "wrong" variable name is returned instead of e.g. NULL.
define("VERSION", "1.0");
echo "Current version: ".VERSIONXXX."."; // Result: "Current version: VERSIONXXX."
One solution I found to get an error message and the return value "NULL" when I accidently entered a wrong constant name is using the function constant():
define("VERSION", "1.0");
echo "Current version: ".constant("VERSIONXXX")."."; // Result: "Current version: ."
Question 2: Can I prevent in a different way, that PHP returns the name of the non-existing variable?
Question 3: Should the value of a constant in PHP always be returned using the function constant()?
If you attempt to use a constant that does not exist, PHP automagically assumes it is a string instead, which is why you see VERSIONXXX.
IIRC it throws a warning if you're error reporting is at the appropriate level. The best solution here is to ensure your code utilizes the proper constant names.
If you know the name of the constant, it's easiest/best to use it directly. echo MY_CONSTANT
If you don't know the name of the constant (e.g. it's name is in a variable), use constant():
$name = 'MY_CONSTANT';
echo constant($name);
In reverse Order:
Question 3: No
Question 2: Not really, but you can make adjustments.
because of (Question 1:) error_reporting. You PHP webserver is configured hide some errors. If you add
error_reporting(E_ALL);
to your scripts head, you will get a
Use of undefined constant MY_CONST - assumed 'MY_CONST'
Error. Unfortunately it's a problem coming out of PHP's long history, that constants can be interpreted as strings.
If you can not be shure a constant was set in the first place you can use defined
if(defined('MY_CONSTANT') {
//do something
}
But my personal opinion there shouldn't be many cases to need this, since the word constant alone implies a garanteed presence. The only exception I can think of is the typical header test.
if(!defined('MY_APP_IS_PRESENT')) {
die('You can not call this file on its own, please use index.php.');
}
And one last tipp: Go and make yourself a errorhandler function, maybe even with firephp?
Well, you could always use defined function to make sure the constant exists. Combined with a ternary statement, you could simply echo an empty string, something like:
echo defined( VERSION ) ? VERSION : "";
Not the best answer, but workable?
PHP manual for defined() is at http://php.net/manual/en/function.defined.php
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Accessing arrays whitout quoting the key
I noticed there's a subtle difference... if I were to code this:
echo "Welcome, $_SESSION['username'], you are logged in.";
It will fail at parsing. However if I code like this:
echo "Welcome, $_SESSION[username], you are logged in.";
It works as expected which makes me wonder if single quotes are really necessary? I cannot find anything in PHP documentation showing that effect.
In PHP, a global constant that isn't defined becomes a string.
Don't rely on this; always quote your array keys.
However, interpolated into a string, it is fine, as it is already a string.
Konforce makes a good point in the comments about using braces in string interpolation.
If you omit them, don't quote the key.
If you use them, you must quote the key, otherwise the constant will be looked up.
This way is wrong but works$_SESSION[username] and take more time to parse the value of that associative index.
That effect PHP performance
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 should use quotes while accessing values.
Please check this document
in section Array do's and don'ts
<?php
// Show all errors
error_reporting(E_ALL);
$arr = array('fruit' => 'apple', 'veggie' => 'carrot');
// Correct
print $arr['fruit']; // apple
print $arr['veggie']; // carrot
// Incorrect. This works but also throws a PHP error of level E_NOTICE because
// of an undefined constant named fruit
//
// Notice: Use of undefined constant fruit - assumed 'fruit' in...
print $arr[fruit]; // apple
// This defines a constant to demonstrate what's going on. The value 'veggie'
// is assigned to a constant named fruit.
define('fruit', 'veggie');
// Notice the difference now
print $arr['fruit']; // apple
print $arr[fruit]; // carrot
// The following is okay, as it's inside a string. Constants are not looked for
// within strings, so no E_NOTICE occurs here
print "Hello $arr[fruit]"; // Hello apple
// With one exception: braces surrounding arrays within strings allows constants
// to be interpreted
print "Hello {$arr[fruit]}"; // Hello carrot
print "Hello {$arr['fruit']}"; // Hello apple
// This will not work, and will result in a parse error, such as:
// Parse error: parse error, expecting T_STRING' or T_VARIABLE' or T_NUM_STRING'
// This of course applies to using superglobals in strings as well
print "Hello $arr['fruit']";
print "Hello $_GET['foo']";
// Concatenation is another option
print "Hello " . $arr['fruit']; // Hello apple
?>
Inside a string you have to omit the single quotes or wrap the whole variable in {} ("...{$array['key']}..." or ...$array[key]...). However, wrapping it is highly recommended to prevent issues when having something like "...$foobar..." where you actually wanted "...{$foo}bar..." (i.e. the var $foo followed by bar).
But you might not want to use in-string vars at all but properly end the string: '...' . $var . '...'
It's called bare strings as mentioned, strangly enough, in the array documentation. If no constant is found matching the bare string - It's, for historical reasons, assumbed to be a string literal. This syntax is however ridden with a lot of syntactic problems that I won't go into, also readability is a problem here. The reader questions himself - Is this a constant or a string?
Modern PHP versions emit a warning for this syntax, as to help fix this problem by using singly quoted strings ('username').
yes.
If you pass an argument for an array without any quotes, php will first try to interpret the argument as a constant and if it isn't defined, it will act as expected.Even though it can give the same result, it is significantly slower that the quoted argument.
Here's an example of when this might not work :
define("a_constant","a value");
$a = array("a_constant"=>"the right value");
echo $a[a_constant];
The a_constant variable has the value "a value", so $a[a_constant] gets translated to $a["a value"], a key which does not exist in the array $a.
I'm trying to get a constant string and index it as if it was an array of characters (square bracket syntax). When I try this code it fails on the last line.
define( 'CONSTANT_STRING','0123456789abcdef');
echo CONSTANT_STRING; // Works by itself :)
$string = CONSTANT_STRING;
echo $string[9]; // Also works by itself.
echo strlen(CONSTANT_STRING); // Also works by itself.
echo substr(CONSTANT_STRING, 9, 1); // Ok, yes this works, but not as clean.
echo CONSTANT_STRING[9]; // Fails as a syntax (parse) error.
I am using a constant string like this in a function. Since it could be called multiple times on one page it really should be a constant. What is the best option if there is no way to do this like I originally intended.
PHP Constants can only be scalar values, so the engine doesn't try to properly parse a constant that's used as something more than a scalar, like an array or an object.
This is a problem in your case because the brackets are used to point at an array index and can be used as a shortcut to grab a character at a specific location in the string.
You'll just have to do it the "hard" way and use substr().
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.