There are a few interactive php shells out there, so I picked one and wrote a drush command that bootstraps a site and opens a php shell (similar to the sql cli command). The command is simply "php". Attached is a zip with all the necessary components.

The php shell code is available here: http://jan.kneschke.de/projects/php-shell

This shell supports readline if you have it, but works just as well without it. Additionally, you can customize it to your liking. I customized this one a bit by changing the output colors, and setting the $_ variable to contain the output from the previous command.

Using Drush with an interactive php shell is ridiculously powerful. I use it all the time to aid in development and debugging. Figured I'd share the tip. :-)

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

moshe weitzman’s picture

Yeah, we surely want something like this. Please lets compare against #543550: Drush interactive mode and pick the best way forward.

srhaber’s picture

I would treat Drush interactive mode and PHP interactive mode as separate features. Drush mode interprets drush commands and is accessible for general users. PHP mode is reserved for raw php and used primarily by developers.

jonhattan’s picture

Issue tags: +readline

Yeah, my first impression was this issue is a duplicate but they target different things. This issue is as a third party integration into drush and problems and similarities of #543550: Drush interactive mode dont apply because they're implemented in `php-shell` and not in the provided drush command.

srhaber: you force colors for a black background. It should also be visible on console with white background. You can see how drush manage it in function `_drush_print_log()` at file includes/drush.inc.

It is also interesting to get some doc or examples as I wasn't able to do anything with your shell :S

Lastly, a related issue: #562888: The readline library

srhaber’s picture

jonhattan: Yeah I customized the shell a bit since I use a dark background. The shell is configurable and has a couple default color schemes you can access by typing one of the following commands:

>> :set background=light # Loads a color scheme suitable for white backgrounds

>> :set background=dark # Loads a color scheme suitable for black backgrounds

I'll look into adding an option to set the color scheme so it's a little more accessible. Until then, try using one of those :set background commands.

The shell degrades gracefully if you don't have readline support. However, if you do have readline, you'll be able to use the up/down arrow keys to view previous commands, use Ctrl-A/E to move around on the prompt, and most importantly use Tab auto-complete to view a list of all possible functions in the namespace.

Here are some sample commands. The shell will keep prompting new lines until all brackets are closed:
>> $u = user_load(1);

>> print_r($u);

>> if (variable_get('site_offline', 1)) {
.. drush_print('Site offline');
.. } else {
.. drush_print('Site online');
.. }

I've found the shell most useful for viewing user and node objects for debugging, and testing new code during module development.

moshe weitzman’s picture

Status: Active » Needs work

been playing with this again. an interesting feature, that sorta duplicates script command but perhaps different enough so they both merit inclusion.

a few needs:

* rename the command to php-cli
* let command table light or dark scheme as an argument?
* perhaps do something about readline as per #562888: The readline library. my macports php seems not to have it.

srhaber’s picture

Thanks for the suggestions Moshe!

I did a little cleanup on this project. The source is available on Github.
http://github.com/srhaber/drush_php_cli

* Renamed the command to php-cli.
* Removed the color feature completely so it uses the terminal default settings.

I'll take a look at the Readline thread. Is there something to look out for specifically? This shell degrades gracefully if it can't find readline. You just won't be able to make use of tab-completion, command history, etc.

There is a Facebook project called phpsh which emulates readline functionality in a php shell. It's written in Python however, so it may be a challenge to integrate with Drush.
http://www.phpsh.org/

I'm not sure what the proper "etiquette" is for using a third-party library in a Drupal project. As a courtesy I could reach out to the original developer. Thoughts?

Also, apologies for the *super late* response here. My job keeps me busy. :-)

izmeez’s picture

subscribing

mariomaric’s picture

Subscribing.

jennifer.chang’s picture

subscribe.

okokokok’s picture

Great feature!

It would be very useful to be able to switch between the available cli's drush is offering.
Most useful to me seems a possibility to quickly go into sql-cli from the php-cli.

I love Python but it doesn't seem right to depend on it for php-cli to work.

maherg’s picture

subscribe.

greg.1.anderson’s picture

Component: Code » PM (dl, en, up ...)

This was brought up again in #952234: REPL code (marked as duplicate). It occurs to me that perhaps this command could be implemented to just use php -a to run php in interactive mode.

progga’s picture

I see that srhaber's php-cli is better than what I have submitted. Since "php -a" is unfortunately not a substitute for a Drupal REPL, php-cli should be included unless its dependency on a PEAR library is a problem. Thanks.

greg.1.anderson’s picture

Why isn't php -a an adequate substitute? It seems that drush could re-launch php -a with a system call, and execute the bootstrap code via --process-begin or --process-file. Then you would get all of the readline goodness and other features of php -a without needing to re-implement it.

jonhattan’s picture

Component: PM (dl, en, up ...) » Core Commands

AFAIK php -a is not an option because there's no way to use it after bootstrap. It is a toy that always starts in a clean state. You can't do php -a drush.php nor php -a < drush.php.

OTOH #562888: The readline library is blocker. If there's no readline it is almost useless. Mmm I think Yoran Brault did something interesting (only for unixes) by using stty.

greg.1.anderson’s picture

Assigned: Unassigned » greg.1.anderson

I'm pretty sure that php -a will work just fine, but I suppose I'll have to prove it with a patch. :)

jonhattan’s picture

I'll love to see such a patch. Note php -a -f file.php is neither an option :)

greg.1.anderson’s picture

php -a --process-begin should work, though, presuming that you pass in a function call to the bootstrap code as the value to --process-begin.

jonhattan’s picture

I didn't know about --process-begin but I think it is neither an option :(

Some tests:

jonhattan@larry:/tmp$ php --process-begin 'print "hello world\n";'
hello world
^C  
jonhattan@larry:/tmp$ php -a --process-begin 'print "hello world\n";'
Either execute direct code, process stdin or use a file.
jonhattan@larry:/tmp$ php -a --process-begin --
Either execute direct code, process stdin or use a file.

no way to make it work...

$ php --help
Usage: php [options] [-f] <file> [--] [args...]
       php [options] -r <code> [--] [args...]
       php [options] [-B <begin_code>] -R <code> [-E <end_code>] [--] [args...]
       php [options] [-B <begin_code>] -F <file> [-E <end_code>] [--] [args...]
       php [options] -- [args...]
       php [options] -a

^^ it seems -a is exclusive.

I've read the implementation. If I'm not wrong, it confirms both options are mutually exclusive.

http://gcov.php.net/PHP_HEAD/lcov_html/var/php_gcov/PHP_HEAD/sapi/cli/ph...

     890                 :                         case 'a':       /* interactive mode */
     891               7 :                                 if (!interactive) {
     892               7 :                                         if (behavior != PHP_MODE_STANDARD) {
     893               1 :                                                 param_error = param_mode_conflict;
     894               1 :                                                 break;
     895                 :                                         }
     896                 : 
     897               6 :                                         interactive=1;
     898                 :                                 }
     899               6 :                                 break;
     900                 : 
     983                 :                         case 'B':
     984               4 :                                 if (behavior == PHP_MODE_PROCESS_STDIN) {
     985               1 :                                         if (exec_begin) {
     986               1 :                                                 param_error = "You can use -B only once.\n";
     987               1 :                                                 break;
     988                 :                                         }
     989               3 :                                 } else if (behavior != PHP_MODE_STANDARD || interactive) {
     990               0 :                                         param_error = param_mode_conflict;
     991               0 :                                         break;
     992                 :                                 }
     993               3 :                                 behavior=PHP_MODE_PROCESS_STDIN;
     994               3 :                                 exec_begin=php_optarg;
     995               3 :                                 break;

param_mode_conflict is:

static const char *param_mode_conflict = "Either execute direct code, process stdin or use a file.\n";
greg.1.anderson’s picture

Darn! I guess php -a really is a toy. :{ Submit a patch to php? :P (I know, we don't want to adjust the version of php that drush depends on...)

I guess it's back to fretting about readline availability, then.

progga’s picture

Actually, when I originally wrote my Drupal REPL in Unix, I wrote it with readline support. Then Facebook's phpsh was released making my code unnecessary. Recently I have started to work at a new place (defaqto.com, who are still hiring) which is a Windows shop and so phpsh would not run. So I dropped the readline calls from my old Drupal REPL code and started using it alongside drush.bat. If you are using Window's command prompt, then you get some readline type functionality built-in (e.g. pressing the up arrow will bring the previous line). So I don't miss the readline functionality much apart from command history. This makes my code mostly relevant to Windows and so I submitted the code to the drush_extra project instead of the drush project. Hope this explains it a bit. Thanks.

greg.1.anderson’s picture

Assigned: greg.1.anderson » Unassigned

I don't have any interest in writing an interactive shell in drush; since php -a won't work, there is no way to make an interactive php mode the same way that drush core-cli works. So, we're back to #6. This command is welcome here, but I won't be working on it.

msonnabaum’s picture

I've been thinking about this lately (its something I've wanted for a while), and I think we can do it fairly easily if we leverage facebook's phpsh:

http://www.phpsh.org/

Attached is a POC drush command that bootstraps the site you run `drush interactive-shell` from. Very rough, but seems to work in my limited testing.

progga’s picture

Just wanted to mention "rlwrap" (http://utopia.knoware.nl/~hlub/uck/rlwrap/rlwrap.html). By wrapping your command in rlwrap (e.g. "rlwrap drush cli", you can get all the readline functionalities. "rlwrap" works in Unix and also under Cygwin. The windows cmd.exe provides line history functionality out of the box, so the absence of rlwrap on Windows is not a problem either.

ilo’s picture

#23 phpsh makes python a requirement for this to work and #24 rlwrap description says: 'rlwrap is a wrapper that uses the GNU readline library to allow the editing of keyboard input for any other command', so using readline seems no need for rlwrap in this case, I guess..

Looking forward the advances on this.

zroger’s picture

I'm in favor of using phpsh. I started a sandbox project (http://drupal.org/sandbox/rz/1100042) before I was pointed to this thread that makes this type of functionality a drush add-on. I've been using this implementation for about a week now and find it very useful. IMHO, it would be a monumental task to match the existing level of functionality in phpsh.

zroger’s picture

Update on phpsh. I have a full project going at http://drupal.org/project/phpsh.

matt2000’s picture

Another entry to the field:

https://github.com/matt2000/phprepl

It's a PHP-REPL that just happens to have a wrapper that bootstraps Drupal using Drush.

matt2000’s picture

Status: Needs work » Needs review
FileSize
3.46 KB

I've added a drush.inc file to phprepl, though that method of launching the shell does not currently support history and tab completion. This could be fixed with a small patch to drush which I recently discussed with Owen Barton.

A few notes on the differences between phprepl and phpshell from the OP's version:

- phprepl uses rlwrap as discussed above to avoid direct dependency on readline
- the php part of phprepl is one relatively short php file, so it's simpler.
- It's not "third-party" per se. I'd happily host the project on d.o and deprecate the github repo. I started to write it as a drush shell specificially, and realized it was cleaner to make the drupal bootstrap a simple wrapper around a general php shell.
- phprepl has some features phpshell lacks -- e.g., support for use of the global keyword, the ability to drop to a multi-line editor (assuming nlwrap is available), simpler syntax for function calls with no arguments; just type 'conf_path' for the equiavlent of 'echo conf_path();'
- On the plus side for phpshell, it looks like it's doing some validation on the input. phprepl currently will try to shove just about anything through eval().
-phpshell also handles fatal errors better.

Unfortunately, I did not find this thread or phpshell before I started writing my own tool, or I would have made an effort to build from that, so there is definitely overlap.

As for phpsh, it looks nice, but I assumed adding a python dependency was a non-starter for the possibility of inclusion in drush.

A tarball is attached for convenience of review.

RobLoach’s picture

If we had #1316322: Add PSR-0 autoloader to drush, Drush could automagically download PHP-REPL for us when needed.

msonnabaum’s picture

Status: Needs review » Needs work

Tried phprepl. Not impressed. The installer requiring sudo for what it's doing is a not reasonable IMO. If it worked with pear or composer, maybe.

Also, python as a dependency for phpsh is in no way a non-starter. Everyone has it installed and phpsh is a very solid project. I'm still in favor of integrating with it.

greg.1.anderson’s picture

Okay, maybe everyone does have python installed, but this is what I had to do to make phpsh work on my system:

sudo apt-get install python-pip
sudo apt-get install python-dev
sudo apt-get install libncurses5-dev
sudo easy_install readline
python setup.py build
sudo python setup.py install

The documentation wasn't clear on where to get easy_install (python-pip), Python.h (python-dev) or ncurses (libncurses5-dev), but the internets helped me. I already have a million packages (well, seems like) installed, so others might need to a little more searching. It is somewhat ironic that "easy_install" runs gcc, and in no way helps you with dependencies. You don't need 'sudo' to run python setup.py install, as it will install locally if you want; however, you do need sudo to get the dependencies you need to compile, if they're not pre-loaded. I don't think that's much of an issue, though.

Once it was installed, though, phpsh, and the Drush phpsh extension pretty well rocked (although why the phpsh Drush command is 'console' instead of 'phpsh' is a mystery to me). I really like the built-in php documentation help feature. It would also be cool if there would be some way to integrate fn-hook and fn-view from devel into phpsh; I did not look into what it would take to extend. I suppose I could always run with two terminals open -- one with bash, and one with phpsh.

Sure would be nice to have a better installer for phpsh; all the same, I wouldn't be opposed to integrating with the Drush phpsh extension if there was a desire to move in that direction.

didlix’s picture

I've got this setup, but when I try to do anything that I would expect to be working in drupal I get errors that the functions don't exist.

Error: Call to undefined function node_load() in /usr/share/php/phprepl/phprepl.php(105) : eval()'d code, line 1

It looks like you're doing a full bootstrap, maybe my understanding of what this gives me is wrong?

matt2000’s picture

@didlix

It works for me.... Can you provide the exact steps to reproduce the error? Make sure you are running the command as `drepl`.

matt2000’s picture

Status: Needs work » Needs review

didlix's issue hasn't been reporduced.

msonnabaum's complaint isn't valid. (installing an app for all users always requires root access, and phprepl doesn't require being installed this way. If it becomes part of Drush, it will be available via PEAR because drush is.)

So is there any consensus on the best way forward among
a.) phpsh (in python)
b.) phpshell (in PHP)
c.) phprepl / drepl (in PHP+BASH)

?

I'm willing to continue to support phprepl, but don't want to waste effort if the community is favoring another choice.

greg.1.anderson’s picture

I don't think that we should use anything package anything into Drush core that is less functional than phpsh. I suspect it would be more efficient to concentrate on collaborating with the more functional projects than to reimplement in php, but that is just my opinion.

moshe weitzman’s picture

I'm not bothered by the Python dependency. I'd love to have http://drupal.org/project/phpsh in Drush core.

moshe weitzman’s picture

Status: Needs review » Active
kscheirer’s picture

For what it's worth, I checked our srhaber's code (#6) from the git repo and everything worked great. No install of anything required, up and running in 5 minutes.

Karls-MacBook-Pro:~ karl$ drush --version
drush version 5.6
Karls-MacBook-Pro:~ karl$ cd .drush
Karls-MacBook-Pro:.drush karl$ git clone https://github.com/srhaber/drush_php_cli.git
Cloning into 'drush_php_cli'...
remote: Counting objects: 53, done.
remote: Compressing objects: 100% (51/51), done.
remote: Total 53 (delta 9), reused 0 (delta 0)
Unpacking objects: 100% (53/53), done.
Karls-MacBook-Pro:.drush karl$ cd ~/www/tabatap3/sites/tp3.localhost/
Karls-MacBook-Pro:tp3.localhost karl$ drush php-cli
PHP-Barebone-Shell - Version 0.3.1, with readline() support
(c) 2006, Jan Kneschke <jan@kneschke.de>

>> use '?' to open the inline help 

>> print VERSION;
6.26
Jody Lynn’s picture

I'm a big user of http://drupal.org/project/phpsh and would love to see it in drush core. I freak out when people don't have it installed and I have to resort to drush php-eval or /devel/php.

dinofile’s picture

thanks. Worked like a treat for me too. Very cool.

holtzermann17’s picture

Version: » 7.x-5.0

I installed phpsh and the corresponding module: it's "nice" but doesn't work out of the box: #1932556: Drupal fails to bootstrap

holtzermann17’s picture

A further note to #42 - phpsh doesn't seem to work well when xdebug is turned on, see for instance https://github.com/facebook/phpsh/issues/41 and other related issues in the phpsh tracker. It seems like the phpsh developers somehow intended that the two systems play well together, but at the moment they really don't!

greg.1.anderson’s picture

Another option: https://github.com/d11wtq/boris

(From a tweet by @moshe weitzman)

yched’s picture

And a drupal loader for boris (#44) : https://github.com/tobiassjosten/boris-loader
Pretty awesome...

moshe weitzman’s picture

Status: Active » Closed (duplicate)

Perhaps all we need is a small wrapper around #45 that launches boris in the right drupal site. Would be nice if it worked for remote sites as well, like core-ssh command.

I'm closing this issue in favor of discussion at https://github.com/drush-ops/drush/issues/11. Lets work there.

patcon’s picture

I absolutely LOVE that this conversation has moved to github...! MUHAHAHA