I was wondering if there was some way to interpolate class constants in strings without storing them in other variables first. Consider the following code:
class Foo {
const BAR = 'baz';
}
$foo = new Foo(); // or $foo = 'Foo';
echo "{$foo::BAR}";
// PHP 5.6: Parse error: syntax error, unexpected '}', expecting '('
// PHP 7.*: Parse error: syntax error, unexpected '}', expecting '['
// PHP 8.0: Parse error: syntax error, unexpected token "}", expecting "->" or "?->" or "{" or "["
The error messages seem to indicate that PHP is expecting an array access operator, and sure enough:
class Foo {
const BAR = 'baz';
}
$foo = new Foo(); // or $foo = 'Foo';
echo "{$foo::BAR[2]}";
// PHP 5.6: Parse error: syntax error, unexpected '[', expecting '('
// PHP 7.*: 'z'
// PHP 8.0: 'z'
Using array access on a string treats it as an array of characters, so this is expected PHP behaviour. If the class constant is set as an array, the full value can be accessed. If the class constant is numeric, it can't be accessed since numerical values don't automatically convert to arrays.
Why does PHP >= 7.0 allow class constants to be accessed as arrays but not as plain strings or numeric values inside a string?
Related
I've seen in this answer the code
$tmpNode = parent::addChild($name,null,$namespace);
$tmpNode->{0} = $value;
I'm curious what the ->{0} actually does? Which PHP language construct is this? Does it reference the first property of $tmpNode without using its name?
Update:
I've seen the answers given so far, but I was looking for a reference into the PHP language manual that explains this use of curly braces. When I search in the PHP Manual for curly the only hit is to the page about strings where curly's are only explained in the context of variables and complex expressions. It wasn't clear to me that the language allows curly's around literals.
Curly brackets {} in php are also used to parse complex codes. Take this for example:
$t = 0;
$$t = 5;
echo ${0}; //outputs 5
or this:
${0} = 65;
echo ${0}; //outputs 65
but if you were to try this:
$0 = 65;
echo $0;
you would get:
Parse error: syntax error, unexpected '0' (T_LNUMBER), expecting variable (T_VARIABLE) or '$'
It is the same with object properties:
$obj = new stdClass();
$obj->{1} = "Hello world";
echo $obj->{1}; //outputs "Hello world"
Complex (curly) syntax
How come in PHP this works:
$myClass = 'App\MyClass';
$object = new $myClass;
But this results in an error:
$myClass = 'MyClass';
$object = new 'App\\'.$myClass;
In the second example, an unexpected T_CONSTANT_ENCAPSED_STRING is thrown.
As it turns out, the above example is due to operator precedence since new takes highest precedence, but...
Similarly, I can try instantiating with just a string as in:
$object = new 'App\MyClass';
And the same error is thrown. Why is this?
The parser's implementation is not generic, therefore in some cases the parser would hiccup over things the engine could in fact handle. There (still) isn't even an official formal grammar for PHP, which makes it hard to predict things like this, without simply trying them out. It's the way of the PHP world :)
PHP expects a variable or name reference for object definitions, it simply won't allow strings. You can use this hack which is based on '' empty string named variable the is instantly created and used based on the fact that ${false} evaluates to ${''} as follows to create an object from string:
$obj = new ${!${''} = 'App\MyClass'}();
PHPs syntax is defined in zend_language_parser.y, and it simply doesn't define any more complex expressions for the new operator:
new_expr:
T_NEW class_name_reference ctor_arguments
{ $$ = zend_ast_create(ZEND_AST_NEW, $2, }
| T_NEW anonymous_class
{ $$ = $2; }
Where class_name_reference is:
class_name_reference:
class_name { $$ = $1; }
| new_variable { $$ = $1; }
And new_variable allows for a limited set of variable expressions:
new_variable:
simple_variable
{ $$ = zend_ast_create(ZEND_AST_VAR, $1); }
| new_variable '[' optional_expr ']'
{ $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
| new_variable '{' expr '}'
{ $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
| new_variable T_OBJECT_OPERATOR property_name
{ $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); }
| class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
{ $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
| new_variable T_PAAMAYIM_NEKUDOTAYIM simple_variable
{ $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
// Copyright (c) 1998-2015 Zend Technologies Ltd., the Zend license 2.00
Which is why you can't have string expressions there. (It was never extended, because the trivial instantiations and $classvarnames are often sufficient. So the allowed syntax is mostly the same as in PHP3, when it was introduced.)
This is because of operator precedence:
http://php.net/manual/en/language.operators.precedence.php
Since 'new' has a higher precedence than '.' it gets processed first.
As far as your code goes, what the compiler sees is:
$myClass = 'MyClass';
$object = new 'App\\';
$object = $object . $myClass;
For the second part of your question, why: $object = new 'App\MyClass'; doesn't work. I am unsure.
If I had to guess I would say it is because when you do new 'App\MyClass', the parser doesn't know it is a string when it encounters it. Until the line has been processed it doesn't know if it is dealing with a string, number, object, etc. It could discover that and properly cast it to a string but I would guess this comes back to operator precedence where it doesn't do those type of casts until after handling the 'new' operator.
Curiously, I just tested it in Quercus PHP and it runs fine. As other people have mentioned, php isn't a fully defined language so things like this manifest as differences between implementations.
I have this PHP code and getting this error:
Parse error: syntax error, unexpected '$e' (T_VARIABLE)
In this line:
$error = echo 'Captured: ', $e->getMessage(), "\n";
I got this information from here. I just wanted to save the echo to a variable. What am I doing wrong here?
Comma is not a concatenation operator in PHP, Period is. Secondly, echo doesn't return the string back, it only outputs it. Remove the echo and save your string in your variable like this:
$error = 'Captured: '. $e->getMessage(). "\n";
Now you may wonder that if this is the case then why do you have an example on PHP.net having comma there?
echo 'Captured: ', $e->getMessage(), "\n";
It is because that is not string concatenation, those are 3 different parameters being sent to the echo command so in that case it is valid syntax, but for string concatenation it wont be.
Today i was working with some codes when I met this error to make it simplify I have made an simple code which returns this error:
$i=1;
echo $i*5."<br/>";
Error
syntax error, unexpected '"<br/>"' (T_CONSTANT_ENCAPSED_STRING), expecting ',' or ';'
Here I am trying to multiply an integer variable with an integer value and then add some string afterwords.
the solution I found to escape this error is to simply replace $i*5 by 5*$i but it my question is why does this happens.In my scope ov view there is no syntax error but if there is any please let me know.
The reason for the error is the . after 5 which makes compiler confused whether 5 is an integer or an floating value i.e it expects some digits after . but it gets "<br/>"
You can add an space after the digit so that the compiler gets to know that number is over like this :
$i=1;
echo $i*5 ."<br/>";
The correct syntax is either
echo $i*5, "<br/>";
// You can echo more than one expression, separating them with comma.
or
echo $i*5 . "<br/>";
// Notice the space.
// 5. is interpreted as ( float ) 5
Look at the code below
<?php
echo "$_SERVER[HTTP_HOST] <br />";
echo $_SERVER['HTTP_HOST'], "\n\n";
?>
both of the echo statements return the value of HTTP_HOST index from the superglobal array $_SERVER using the same technique? My question is what caused the difference of the syntax? I noticed the following differences:
HTTP_HOST in the first echo statement is not encased in single quotes, it is contrary to the syntax I used in the second echo statement. I get the following error if I encase HTTP_HOST in single quotes for the first echo statement
Parse error: syntax error, unexpected '' (T_ENCAPSED_AND_WHITESPACE), expecting identifier (T_STRING) or variable (T_VARIABLE) or number (T_NUM_STRING) in C:\xampp\htdocs\php-blog\simple-blog\server.php on line 2
Why a comma is needed after ['HTTP_HOST'] in the second echo statement while it is not needed in the first echo statement? I get the following error if I discard this comma.
Parse error: syntax error, unexpected '"\n\n"' (T_CONSTANT_ENCAPSED_STRING), expecting ',' or ';' in C:\xampp\htdocs\php-blog\simple-blog\server.php on line 3
I am new to programming, need guidance, help please.
Thank you!
Your first statement calls echo with only one argument.
The argument is a string which includes a variable.
When doing this you should use brackets to make sure php understands were your variable starts:
echo "{$_SERVER['HTTP_HOST']} <br>";
You could also concatenate strings with a dot:
echo $_SERVER['HTTP_HOST'] . "<br>";
The comma is just another way to write several echos at once:
echo 1, 2;
is the same as
echo 1;
echo 2;
http://php.net/manual/en/function.echo.php
php syntax allows referring to variables inside double-quotes.
for example:
$x = "hello";
echo "$x world";
is similar to:
echo $x . " world";
or
echo $x , " world";
and all will output hello world.
notice that referring to variables inside single-quotes is not allowed, and for this reason
echo '$x world';
is invalid.