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().
Related
So... This is more of a curiosity, not a real problem. I don't get this:
<?php
define('EMPTY', 1);
echo EMPTY;
Results in: Parse error: syntax error, unexpected ';', expecting '('
My first thought is that empty is reserved for the empty function. But then I tried:
<?php
define('IS_ARRAY', 1);
echo IS_ARRAY;
Result: 1
So... I don't get it. Why empty can't be used as constant while for example is_array, die, etc. can.
empty is not a function but a language construct (more like an operator than a function), which means it's resolved by the parser at parse time and not by the runtime. It's a reserved keyword and you cannot use it for anything yourself like function names, or constants.
The reason empty cannot be a regular function is because it behaves differently. empty($undefined) would first resolve $undefined, throw an error, then pass null to empty; which is exactly the case empty is supposed to prevent, so it cannot play by the normal function invocation rules.
empty is a reserved keyword in PHP. You cannot use any reserved words as constants, class names, function or method names as these words have special meaning in PHP. Use any other name as constant.
You can definately define "EMPTY" as a constant. The problem is you can't use it directly.
<?php
define("EMPTY", "valueForEmpty");
echo EMPTY; // Wont work because empty is a keyword and PHP doesn't know that you mean the constant.
echo constant("EMPTY"); // Works
Note that the reserved keywords are also case insensitive, and they can't be defined as constant or redefined using runkit_function_redefine();
You can find here the exhaustive list of reserved keywords
I recently saw this line in a PHP piece of code:
$dbObject = json_decode($jsonString);
$dbObject->{'mysql-5.4'}[0]->credentials
What does this mean? In the PHP docs we can read, that
Both square brackets and curly braces can be used interchangeably for accessing array elements (e.g. $array[42] and $array{42} will both do the same thing in the example above).
But how can the Object $dbObject be defined to allow ->{...}[...]access? Is this code kind of unsafe? Which PHP version does allow this?
Did I miss anything in the PHP docs?
It's to enable access to properties which would be invalid syntax as bare literals. Meaning:
$dbObject->mysql-5.4[0]->credentials
This is invalid/ambiguous syntax. To make clear to PHP that mysql-5.4 is a property and not a property minus a float, you need to use the {'..'} syntax.
To be exact, ->{..} enables you to use any expression as the property name. For example:
$dbObject->{ sprintf('%s-%.1f', 'mysql', 5.4) }
The curly brace syntax allows you to use a string literal or variable as a property or method name.
This is useful for several reasons:
(per #Deceze's answer): It allows you to access property names that would otherwise not be valid PHP syntax -- eg if the property name contains a dot or dash, per your example. Typically properties like this would be accessed via a __get() magic method, since they would also be invalid syntax to define as an actual property within the class.
(per #feela's answer): It allows you to use variables to reference your properties. This is similar to the $$ variable variable syntax. It's generally not really very good practice, but is useful in some cases.
(not mentioned by any other answers yet): It allows you to remove certain potential ambiguities from your code. Consider the following code for example:
$output = $foo->$bar['baz'];
This is ambiguous. You can resolve the ambiguity by adding braces or brackets:
$output = $foo->{$bar['baz']}; //gets the value of a property from $foo which has a name that is defined in $bar['baz']
$output = ($foo->$bar)['baz']; //gets the ['baz'] element of $foo->$bar array.
This is particularly important because the forthcoming relese of PHP 7 will change the default behaviour of code like like. This will make the language behave more consistently, but will break existing code that doesn't have the braces.
See also the PHP documentation for this change here: https://wiki.php.net/rfc/uniform_variable_syntax
But even without the language change to force the issue, code like this should have braces anyway to help with readability -- if you don't put braces, then you may end up struggling to work out what you were trying to do when you come back to the code in six months' time.
The curly braces syntax in the example is not from the array syntax, but comes from a possible syntax to access variables with variable names.
Curly braces may also be used, to clearly delimit the property name.
They are most useful when accessing values within a property that
contains an array, when the property name is made of mulitple parts,
or when the property name contains characters that are not otherwise
valid (e.g. from json_decode() or SimpleXML).
Examples from the PHP docs:
echo $foo->{$baz[1]} . "\n";
echo $foo->{$start . $end} . "\n";
echo $foo->{$arr[1]} . "\n";
See “PHP Variable variables”: http://php.net/manual/en/language.variables.variable.php
(More examples on the usage there…)
As an addition to #deceze's answer:
The -> operator means that you are accessing an object property. In this case the property name should be mysql-5.4 which is not valid PHP identifier (it must contain letters, numbers or underscores, see here). So it is 100% sure that the property name has been created dynamically.
PHP allows overloading properties using magic method called __get(). The body of this method allows you to handle any property you would wish - this can be any string, or any variable, even an object, which is cast to a string.
So in your case somebody created a class with a __get() magic method that handles string mysql-5.4. The curly braces { and } are given to denote that the string should be treated as property name (however there is no property with this name).
most of the time there is a $ after ->{ so it's like ->$variable
for example we have:
$languageCode = 'en';
$obj->{$languageCode};
$obj->{$languageCode} it is equivalent to $obj->en
============
in your case it's because it's not allowed in php write like:
$dbObject->mysql-5.4
because there is a - and there is a . in the mysql-5.4 and - and . makes a word to two words.
so you have to write it like this:
$dbObject->{'mysql-5.4'}[0]->credentials
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.
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.
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.