The command-shell.php program shown in Example 20-1 provides a shell-like prompt to let you execute PHP code interactively. It reads in lines using readline( ) and then runs them with eval( ). By default, it runs each line after it's typed in. In multiline mode (specified with -m or --multiline), however, it keeps reading lines until you enter . on a line by itself; it then runs the accumulated code.
Additionally, command-shell.php uses the Readline word-completion features to more easily enter PHP functions. Enter a few characters and hit Tab to see a list of functions that match the characters you've typed.
This program is helpful for running snippets of code interactively or testing different commands. The variables, functions, and classes defined in each line of code stay defined until you quit the program, so you can test different database queries, for example:
% php -q command-shell.php [1]> require 'DB.php'; [2]> $dbh = DB::connect('mysql://user:pwd@localhost/phpc'); [3]> print_r($dbh->getAssoc('SELECT sign,planet,start_day FROM zodiac WHERE element LIKE "water"')); Array ( [Cancer] => Array ( [0] => Moon [1] => 22 ) [Scorpio] => Array ( [0] => Mars [1] => 24 ) [Pisces] => Array ( [0] => Neptune [1] => 19 ) )
The code for command-shell.php is in Example 20-1.
// Load the readline library if (! function_exists('readline')) { dl('readline.'. (((strtoupper(substr(PHP_OS,0,3))) == 'WIN')?'dll':'so')) or die("Readline library required\n"); } // Load the Console_Getopt class require 'Console/Getopt.php'; $o = new Console_Getopt; $opts = $o->getopt($o->readPHPArgv(),'hm',array('help','multiline')); // Quit with a usage message if the arguments are bad if (PEAR::isError($opts)) { print $opts->getMessage(); print "\n"; usage(); } // default is to evaluate each command as it's entered $multiline = false; foreach ($opts[0] as $opt) { // remove any leading -s $opt[0] = preg_replace('/^-+/','',$opt[0]); // check the first character of the argument switch($opt[0][0]) { case 'h': // display help usage(); break; case 'm': $multiline = true; break; } } // set up error display ini_set('display_errors',false); ini_set('log_errors',true); // build readline completion table $functions = get_defined_functions(); foreach ($functions['internal'] as $k => $v) { $functions['internal'][$k] = "$v("; } function function_list($line) { return $GLOBALS['functions']['internal']; } readline_completion_function('function_list'); $cmd = ''; $cmd_count = 1; while (true) { // get a line of input from the user $s = readline("[$cmd_count]> "); // add it to the command history readline_add_history($s); // if we're in multiline mode: if ($multiline) { // if just a "." has been entered if ('.' == rtrim($s)) { // eval() the code eval($cmd); // clear out the accumulated code $cmd = ''; // increment the command count $cmd_count++; // start the next prompt on a new line print "\n"; } else { /* otherwise, add the new line to the accumulated code tacking on a newline prevents //-style comments from commenting out the rest of the lines entered */ $cmd .= $s."\n";; } } else { // if we're not in multiline mode, eval() the line eval($s); // increment the command count $cmd_count++; // start the next prompt in a new line print "\n"; } } // display helpful usage information function usage() { $my_name = $_SERVER['argv'][0]; print<<<_USAGE_ Usage: $my_name [-h|--help] [-m|--multiline] -h, --help: display this help -m, --multiline: execute accumulated code when "." is entered by itself on a line. The default is to execute each line after it is entered. _USAGE_; exit(-1); }
Copyright © 2003 O'Reilly & Associates. All rights reserved.