Syntax error with array access in string interpolation
I have only used this library through another library, but here's a reproducible code:
$ composer require opis/closure
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Opis\Closure\SerializableClosure;
$object = new SerializableClosure(function (): string {
$a = new \ArrayObject(['foo' => 'bar']);
return "$a[foo]";
});
$function = unserialize(serialize($object));
var_dump($function());
Result (version 3.5.5):
PHP Parse error: syntax error, unexpected '' (T_ENCAPSED_AND_WHITESPACE), expecting '-' or identifier (T_STRING) or variable (T_VARIABLE) or number (T_NUM_STRING) in closure://function (): string {
$a = new \ArrayObject(['foo' => 'bar']);
return "$a[\foo]";
} on line 5
Result (commit https://github.com/opis/closure/commit/82cc21fefe5f4a56c7c29233129959cb005eb205):
string(3) "bar"
I think the problematic commit is https://github.com/opis/closure/commit/c17ece00ae2f48bbf640482ed699120af330a31c
Of course a workaround is to "fix" all interpolations like this with
return "{$a['foo']}";
You actually need to always put those single quotes in. The other code you have will generate a warning saying constant 'foo' undefined, treated as string, in PHP 5 and 7, and in PHP 8 will be a hard error.
So, this is actually not a bug, and it is doing the correct thing, to escape the constant to the global namespace with a slash.
AFAIK string interpolation has different rules, e.g. theres two are different:
$a = ['foo' => 'bar'];
print $a[foo]; // references a nonexistant constant, emits a warning
print "$a[foo]"; // "knows" the context, this does not emit a warning
See https://www.php.net/manual/en/language.types.string.php Example 10 which uses this syntax.
I tried it with a PHP 8 Docker image too:
$ docker run --rm -it keinos/php8-jit
Interactive shell
php > print phpversion();
8.0.0-dev
php > $a = ['foo' => 'bar'];
php > print "$a[foo]";
bar
php > print $a[foo];
Warning: Uncaught Error: Undefined constant 'foo' in php shell code:1
Stack trace:
#0 {main}
thrown in php shell code on line 1
Ah, yes. You are right! Hmmm. There is a bug here then. :+1:
Hello there, I have experienced troubles with string interpolations too, but that does not only occur with arrays. I created a repo with some tests :
https://github.com/n00dl3/opis-closure-tests
I also tried with @abdrzakoxa PR (branch abdrzakoxa-pr on the test repo), but it only fixes simple array syntax.
Maybe I should open a new issue ?
Yes, please open a new issue. Meanwhile I'll check to see where the problem is.
It would have been very helpful to put those tests directly inside opis/closure :)
Ok, I've found the problem, a fix is coming in the next minutes.
It would have been very helpful to put those tests directly inside opis/closure :)
Yeah, sorry, I started with a single test case and it grew up very quickly...
String interpolation error was solved in https://github.com/opis/closure/commit/85fec0b113e163c343c9d643744bc1221641f0b9 A new version will be released soon.
This issue (with array access) is not solved yet.
Hello @sorinsarca How about my PR, it solves this issue!
@abdrzakoxa I'm looking at that PR right now.