5

Suppose I run the following in a PHP interactive shell, requiring a utility function file with all code under the namespace utils:

php > require_once __DIR__ . '/utils.php';
php > echo \utils\doubleMe(2);
4
php > use \utils as u;
php > echo u\doubleMe(2);
PHP Warning: Uncaught Error: Call to undefined function u\doubleMe() in php shell code: 1
Stack trace: ...
php >

I can call the functions using the fully qualified namespace without issue, however, when I try to use/alias the namespace, it's as if it never happened, and attempts to call functions under the aliased namespace error, saying the function is undefined.

How should I use a namespace in PHP's Interactive Shell? If it's simply not possible, is there any particular reason why?

Samuel Ludwig
  • 111
  • 1
  • 7
  • 1
    Hopefully someone else can provide more information about this because I'm really curious as well, but as noted in [this answer](https://stackoverflow.com/questions/63311320/why-auto-prepend-file-take-no-effect-in-phps-interactive-mode), `use` statements do work, but only if they're used on the *same line*. Try `use \utils as u; echo u\doubleMe(2);` – iainn Jan 11 '21 at 22:56
  • Ah, I never came across this question before; interesting, but my that makes it quite use-less (ha) doesn't it? Would definitely like to know why that is. It's not like the environment (or whatever you'd call it) is being refreshed every command, as the required file's functions are still accessible. – Samuel Ludwig Jan 11 '21 at 23:01
  • 1
    For anyone dejected that this is not possible in PHP's Interactive shell, PsySH seems to be a very viable substitute that does support this (and provides a much more proper PHP REPL experience). https://github.com/bobthecow/psysh – Samuel Ludwig Jan 12 '21 at 13:51

1 Answers1

5

PHP use statements are essentially the compiler performing a copy-paste operation on all code in the buffer. So

use Foo\Bar\Baz as F;
new F();

becomes just

new \Foo\Bar\Baz();

before it gets interpreted.

In a standard flow, the compiler is operating on a single file at a time, so a use statement applies to all code in the given file. But with an interactive shell, the buffer only contains a single line. I mentioned this in a comment, but as noted in this answer, running something like

use \DateTime as D; echo (new D)->format('c');

in an interactive shell will actually work fine, and you'll see something like

2021-01-11T23:24:55+00:00

Putting a use statement on its own line, however, will do essentially nothing; the compiler tries to run its regular "copy-paste" routine, but once that's complete, nothing about the statement is kept in memory, so future lines are not affected.

It's something that I'm sure could be fixed given enough motivation by the Internals team, but I can't find any discussion about it in either the bug tracker or the internals mailing list, and I don't think the interactive shell is generally near the top of any priorities.

iainn
  • 16,826
  • 9
  • 33
  • 40
  • > _I don't think the interactive shell is generally near the top of any priorities._ Mmm, unfortunate, but I do understand. – Samuel Ludwig Jan 12 '21 at 02:06