PHP ignoring to check Constant when array index passed without quote - php

$foo=['hello' => "Hello"];
echo $foo['hello']; // it works as we are doing in normal way
echo "$foo['hello']"; // it throws T_ENCAPSED_AND_WHITESPACE error when we use same variable double quote
echo $foo[hello]; // Throwing error Use of undefined constant.
echo "$foo[hello]"; // Strange!!! it WORKS because not checking constants are skipped in quotes
I am very surprised in echo "$foo[hello]"; because not checking hello index as constant. Exactly I want to know reason behind this?

Because that's how PHP's simple string parsing works. It's not PHP array syntax, it's string interpolation syntax.
Well documented: http://php.net/manual/en/language.types.string.php#language.types.string.parsing.

From manual:
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.
and
Note: To reiterate, inside a double-quoted string, it's valid to not surround array indexes with quotes so "$foo[bar]" is valid. See the above examples for details on why as well as the section on variable parsing in strings.
In manual see: Array do's and don'ts

Related

Is there any way to use function in PHP double quote string?

In JavaScript , you can do this:
const str = `${capitalize(name)} is cool.`;
Can you do the same with PHP double quote string?
Especially if the function is not a method of some instance (not calling a function pointer from variable)
This does not seem to work:
$str = "ucfirst($faker->word) $faker->buildingNumber";
No, sorry, there's nothing like that built into PHP.
The Strings documentation describes the kinds of substitutions that are done inside double-quoted strings and heredocs.
When a string is specified in double quotes or with heredoc, variables are parsed within it.
There are two types of syntax: a simple one and a complex one. The simple syntax is the most common and convenient. It provides a way to embed a variable, an array value, or an object property in a string with a minimum of effort.
The complex syntax can be recognised by the curly braces surrounding the expression.
...
Complex syntax
Any scalar variable, array element or object property with a string representation can be included via this syntax.
Neither the simple nor complex syntax can be used to include a function call.

How to stop PHP from assuming string contains variable

I've been trying to find solution somewhere for this possibly simple fix but, I haven't been able to surprisingly.
How is it possible to stop PHP from assuming a variable is a part of a string. E.g.
The line of code is $string = "slfnnwnfkw49828323$dgjkt^7ktlskegjejke";
how do you stop PHP from thinking '$dgjkt' is a variable within the string when it's really a part of the full string as characters. Thanks
Use this string like $sting = 'slfnnwnfkw49828323$dgjkt^7ktlskegjejke'
You have to use ' instead of " otherwise php tries to find any variables inside your string
Read the manual.
The most important feature of double-quoted strings is the fact that
variable names will be expanded. See string parsing for details:
When a string is specified in double quotes or with heredoc, variables are parsed within it.
There are two types of syntax: a simple one and a complex one. The
simple syntax is the most common and convenient. It provides a way to
embed a variable, an array value, or an object property in a string
with a minimum of effort.
The complex syntax can be recognised by the curly braces surrounding
the expression.

PHP string interpolation syntax

I tried to do redirect with this syntax:
header("location: readMore.php?id=$post['post_id']");
But it didn't work. It worked only after someone suggested to put curly brackets around $post['post_id']!
The correct syntax is:
header("location: readMore.php?id={$post['post_id']}");
What does the curly brackets do in this case?
Quoting the manual:
When a string is specified in double quotes or with heredoc, variables are parsed within it.
There are two types of syntax: a simple one and a complex one. The simple syntax is the most common and convenient. It provides a way to embed a variable, an array value, or an object property in a string with a minimum of effort.
The complex syntax can be recognised by the curly braces surrounding the expression.
Your first code uses simple syntax, and your second code uses a complex one.
The manual does not explicitly state this, but whitespace in simple syntax seems to be an error, rendering your first code invalid. Complex syntax appears to support the same syntax as regular PHP does as far as I can see, but again this does not seem to be actually guaranteed anywhere.
String interpolation is quite flunky in general:
$a = [['derp']];
$b = $a[0];
// Works. It prints derp
echo "$b[0]";
// Doesn't work. It throws an error
echo "$b[ 0 ]";
// Works. It prints derp
echo "{$b[ 0 ]}";
// Doesn't work. It prints Array[0]
echo "$a[0][0]";
// Works. It prints derp
echo "{$a[0][0]}";
// Doesn't work. It prints { Array[0] }
echo "{ $a[0][0] }";
You get similar issues with $object -> foo and $object->foo->bar.
To me, that is pure madness. For that reason I've come to avoid double quoted strings whenever possible (the only thing I used them for are for escape sequences like "\n"). I instead use single quotes and string concatenation, like so:
header( 'location: readMore.php?id=' . $post[ 'post_id' ] );
This lets you use actual PHP syntax for variables without the horrible death trap that is string interpolation.
I came to this question to know more about constant interpolation syntax when those PHP "<<<" things are used to create multiline strings called Heredocs (which allow variable interpolation, unlike Nowdocs).
However, it seems there is no specific syntax for them, and therefore a simple workaround is to create a closure to do so. In here it is just an anonymous function assigned to a variable that will be invoked with parameters:
$int = 'intruder'; // Variable
define('con', '"smart"'); // Constant
// For complex interpolation:
// 1. Define a closure (anonymous function)
// 2. Assign it to a variable with a short name (e.g.: _ )
// 3. Invoke the function by calling the variable with parameters enclosed in ()
$_ = function ($val){return $val;};
$doc = <<<TXT
Hi there,
One day I caught this $int nearby.
I was then told that actually other {$_(con)} $int was there before.
So who came first, the chicken or the egg?
TXT; // Heredoc
echo $doc;
Output:
Hi there,
One day I caught this intruder nearby.
I was then told that actually other "smart" intruder was there before.
So who came first, the chicken or the egg?
You can test the above online on 3v4l. This was based on this answer with a few more examples with operations inside the interpolation brackets.
When you use double or single quotes, PHP will treat whatever is in it as a string unless you tell it that it’s a variable. PHP understands anything after { followed by $ as a variable and treats it as such. Here is an example:
$Text = "XYz";
echo "name-{$Text}";
The other alternative method is to use concatenation. Here is an example:
header("location: readMore.php?id=" . $post['post_id']);
Brackets allow PHP to read what's inside as a variable. You can do that this way too:
header("location: readMore.php?id=" . $post['post_id']);
PHP's simple string interpolation doesn't recognize quoted array keys, which your example demonstrates perfectly. In fact, the correct way to write this is exactly opposite depending on which syntax used: simple vs complex.
Simple syntax - Wrong
Quoted keys cannot be parsed.
header("location: readMore.php?id=$post['post_id']");
Simple syntax - Right
The unquoted string is the associative array key.
header("location: readMore.php?id=$post[post_id]");
Complex syntax - Wrong
It will work, but only if post_id is a defined constant. If not, you'll get a PHP warning.
header("location: readMore.php?id={$post[post_id]}");
Complex syntax - Right
Written just like outside the string.
header("location: readMore.php?id={$post['post_id']}");
To quote the manual on the complex syntax:
// Works, quoted keys only work using the curly brace syntax
echo "This works: {$arr['key']}";
I'd recommend using complex (curly brace) syntax if using quoted keys. And you really should be using them, because outside the string interpolation unquoted keys are actually constants. It's too bad the simple syntax won't allow them, because it makes code reviews and updating old PHP code more difficult.

Which is better to use: $arrayName['literal'] or $arrayName[literal]?

Both are working fine. I'm just curious how php parse the two. Do they have difference on speed, efficiency, etc. Why does php allow us to use both?
Difference is that the first ('literal') is a string key and that the second one is undefined constant. PHP allows you to use both because devs tried to fix bad code of people who weren't paying attention while reading the docs. There's a difference in speed since the second one will raise a warning - undefined constant. Basically, don't use the second one.
if you are using just literal php recognizes this as a constant. So it try to find that constant, and if it fails - it just assumes that your desire was using string literal 'literal'. But, to indicate that it doesn't found the constant it raises Notice level error.
So, using just literal have tweo drawbacks:
If you have constant literal defined - you'll get it's value (and this is a correct usage), not string 'literal'
You'll receive a Notice if you don't have such constant.
So, don't use just literal unless you have a constant with that name defined.
$arrayName[literal] is bad because if you have constant named literal, you'll get unexpected results. When it's no constant named literal, php transforms literal to string 'literal'
http://php.net/manual/en/language.types.array.php
Array do's and don'ts
*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.

How to use $_SERVER['REQUEST_URI']

Is there any difference between typing:
<?php echo $_SERVER[REQUEST_URI] ?>
or
<?php echo $_SERVER['REQUEST_URI'] ?>
or
<?php echo $_SERVER["REQUEST_URI"] ?>
?
They all work... I use the first one.
Maybe one is faster than the other?
Without quotes PHP interprets the REQUEST_URI as a constant but corrects your typo error if there is no such constant and interprets it as string.
When error_reporting includes E_NOTICE, you would probably get an error such as:
Notice: Use of undefined constant REQUEST_URI - assumed 'REQUEST_URI' in <file path> on line <line number>
But if there is a constant with this name, PHP will use the constant’s value instead. (See also Array do's and don'ts)
So always use quotes when you mean a string. Otherwise it can have unwanted side effects.
And for the difference of single and double quoted strings, see the PHP manual about strings.
The first one is wrong - you're actually looking for a constant REQUEST_URI that doesn't exist. This will generate a notice-level warning.
There's no difference between the other two.
There is a difference between single and double quotes in PHP string handling. A string enclosed in double quotes will be evaluated for embedded variables and escape characters (e.g. \n); a string enclosed in single quotes won't (or not as much).
So, for example,
$hello = "world";
echo "Hello $hello!\n";
echo 'Hello $hello!\n';
echo 'Done';
will output
Hello world!Hello $hello!\nDone
In situations where you have no escape characters or embedded variables, it is slightly more efficient to use single quotes as it requires less processing of the string by the runtime. However, many people (me included) prefer to use double quotes for all strings to save confusion.
As a caveat to Gumbo's answer the third representation - double quotes - actually makes PHP look for variables inside that string. Thus that method might be a little slower (although in a string of 11 characters it'll be negligible - it's better practice not to make PHP do that however).
When PHP comes across plain strings being used as array keys it checks if there is a constant with that name and if there isn't it defaults it back to an array key. Therefore, not using quote marks causes a slight performance hit and there is a possibility that the result will not be what you expect.
$_SERVER[REQUEST_URI]
is syntatically incorrect and AFAIK will not run on a default installation of PHP5. The array index is a string so it needs to be passed on strings. I know PHP4 converted undefined constants to strings inside the square brackets but it's still not good practice.
EDIT: Well unless you define a constant called REQUEST_URI, which you haven't in your example script.
$_SERVER['REQUEST_URI']
is the standard method and what you should be using.
$_SERVER["REQUEST_URI"]
also works and while not wrong is slightly more work for the PHP interpreter so unless you need to parse it for variables should not be used. (and if you need to do so, you need to rethink that part of your program.

Categories