• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • readline()

    (PHP 4, PHP 5, PHP 7)

    读取一行

    说明

    readline([string $prompt]): string

    从用户端读取一行.你必须自己使用readline_add_history()将这一行添加到历史记录中

    参数

    $prompt

    你可以指定一个字符串来作为用户的提示信息

    返回值

    从用户端返回一个行字符串.返回的该行的行尾换行符会被删除

    范例

    readline() Example

    <?php
    //get 3 commands from user
    for ($i=0; $i < 3; $i++) {
            $line = readline("Command: ");
            readline_add_history($line);
    }
    //dump history
    print_r(readline_list_history());
    //dump variables
    print_r(readline_info());
    ?>
    
    The readline library is not available on Windows.
    <?php
    if (PHP_OS == 'WINNT') {
     echo '$ ';
     $line = stream_get_line(STDIN, 1024, PHP_EOL);
    } else {
     $line = readline('$ ');
    }
    ?>
    
    Works under windows, and under php 7.2.0 :
    $arr = [];
    for ($i=0; $i < 3; $i++) {
        $arr[$i] = readline("Commande : ");
    }
    // Output
    print_r($arr);
    ----------
    Output:
    Commande : 658
    Commande : 965
    Commande : 478
    Array
    (
      [0] => 658
      [1] => 965
      [2] => 478
    )
    If your CLI script accepts input from STDIN and you also want it to prompt for a password (e.g. as mysql client does), then readline() won't work for you. 
    What you need to do is read from the terminal device as shown below.
    function readline_terminal($prompt = '') {
      $prompt && print $prompt;
      $terminal_device = '/dev/tty';
      $h = fopen($terminal_device, 'r');
      if ($h === false) {
        #throw new RuntimeException("Failed to open terminal device $terminal_device");
        return false; # probably not running in a terminal.
      }
      $line = rtrim(fgets($h),"\r\n");
      fclose($h);
      return $line;
    }
    $pass = readline_terminal('Password: ');
    Note that readline() will return boolean "false" when the user presses CTRL+D.
    A workaround if readline is not compiled into php, because for example the command is only needed within an installation routine. It works as follows under Linux:
    $f=popen("read; echo \$REPLY","r");
    $input=fgets($f,100);
    pclose($f);    
    echo "Entered: $input\n";
    If you want to prefill the prompt with something when using readline, this worked for me:
    <?php
     function readline_callback($ret)
     {
      global $prompt_answer, $prompt_finished;
      $prompt_answer = $ret;
      $prompt_finished = TRUE;
      readline_callback_handler_remove();
     }
     readline_callback_handler_install('Enter some text> ',
                      'readline_callback');
     $prefill = 'foobar';
     for ($i = 0; $i < strlen($prefill); $i++)
     {
      readline_info('pending_input', substr($prefill, $i, 1));
      readline_callback_read_char();
     }
     $prompt_finished = FALSE;
     $prompt_answer = FALSE;
     while (!$prompt_finished)
      readline_callback_read_char();
     echo 'You wrote: ' . $prompt_answer . "\n";
    ?>
    
    To haukew at gmail dot com: 
    readline provides more features than reading a single line of input ... your example misses line editing and history. If you don't need that, use something as simple as this:
    function readline( $prompt = '' )
    {
      echo $prompt;
      return rtrim( fgets( STDIN ), "\n" );
    }
    In CGI mode be sure to call:
    ob_implicit_flush(true);
    at the top of your script if you want to be able to output data before and after the prompt.
    -- Tomas V.V.Cox
    If you want to block remove previous text and wonder that an empty string does not work: the workaround is to use an space with cursor left:
    <?php
    echo "> ";
    readline(" \e[D");
    ?>
    
    <?php
    class ConsoleQuestion
    {
      function readline()
      {
        return rtrim(fgets(STDIN));
      }
    }
    //Example1
    $line = new ConsoleQuestion();
    $prompt = "What Is Your Name: ";
    echo $prompt;
    $answer = $line->readline();
    echo "You Entered: " . $answer;
    //Example2 (comment Ex1 then uncomment Ex2)
    /*$prompt = "What Is Your Name: ";
    echo $prompt;
    $answer = "You Entered: " . rtrim( fgets( STDIN ));
    echo $answer;*/
    ?>
    
    I wanted a function that would timeout if readline was waiting too long... this works on php CLI on linux:
    <?php
    function readline_timeout($sec, $def)
    {
      return trim(shell_exec('bash -c ' .
        escapeshellarg('phprlto=' .
          escapeshellarg($def) . ';' .
          'read -t ' . ((int)$sec) . ' phprlto;' .
          'echo "$phprlto"')));
    }
    ?>
    Just call readline_timeout(5, 'whatever') to either read something from stdin, or timeout in 5 seconds and default to 'whatever'. I tried just using shell_exec without relying on bash -c, but that didn't work for me, so I had to go the round about way.
    a few observations....
    I use Cygwin PHP v7 and readline is available. The readline_list_history() function though is not defined.
    A prompt with escape sequences are sanitized, so use something like:
    <?php
      echo("\e[0m\e[34mPromt>\e[0m");
      $inp = readline(' ');
    ?>
    I have not fully documented it, but I see that sometimes strings beginning with punctuation characters do not make it into the history with readline_add_history(). They also sometimes clear the prompt string.