CascadiaPHP 2024

readline

(PHP 4, PHP 5, PHP 7, PHP 8)

readline一行読み込む

説明

readline(?string $prompt = null): string|false

ユーザーからの入力を一行読み込みます。 この行を readline_add_history() を用いてヒストリに追加する必要があります。

パラメータ

prompt

ユーザーに示す確認文字列を指定します。

戻り値

ユーザーから取得した文字列を一つだけ返します。 戻り値の最後の改行は取り除かれます。 読み取るデータが残っていない場合、false を返します。

例1 readline() の例

<?php
// ユーザーから 3 回コマンドを取得
for ($i=0; $i < 3; $i++) {
$line = readline("Command: ");
readline_add_history($line);
}

// ヒストリをダンプ
print_r(readline_list_history());

// 変数をダンプ
print_r(readline_info());
?>

add a note

User Contributed Notes 17 notes

up
17
Antony Penn
4 years ago
Christian's code works well, but if you want to be able to hide the user input and not echo it to screen, you need to add -s to the read command. The code below is an expanded function that allows an optional prompt and optional hiding of the input:

function read_password($prompt=null, $hide=false)
{
if($prompt) print $prompt;
$s = ($hide) ? '-s' : '';
$f=popen("read $s; echo \$REPLY","r");
$input=fgets($f,100);
pclose($f);
if($hide) print "\n";
return $input;
}
up
8
turdsurfer
7 years ago
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: ');
up
1
cox at idecnet dot com
22 years ago
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
up
1
Anonymous
13 years ago
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('$ ');
}
?>
up
0
Anonymous
7 years ago
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.
up
0
rojaro at gmail dot com
15 years ago
Note that readline() will return boolean "false" when the user presses CTRL+D.
up
0
soletan at toxa dot de
17 years ago
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" );
}
up
-1
sean
15 years ago
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.
up
-1
mfuhrman at enetarch dot net
1 year ago
To stop auto complete , register an auto complete function that returns no matches to auto complete.

function dontAutoComplete ($input, $index)
{ return ([]); }

readline_completion_function ("dontAutoComplete");
up
-2
christian at gaeking dot de
20 years ago
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";
up
-2
taneli at crasman dot fi
15 years ago
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";
?>
up
-2
divinity76+spam at gmail dot com
2 years ago
for some reason readline() doesn't support unicode, readline STRIPS æøåÆØÅ - for a readline function with unicode support, try
<?php
function readline_with_unicode_support(?string $prompt = null)/*: string|false*/
{
if (
$prompt !== null && $prompt !== '') {
echo
$prompt;
}
$line = fgets(STDIN);
// readline() removes the trailing newline, fgets does not,
// to emulate the real readline(), we also need to remove it
if ($line !== false && strlen($line) >= strlen(PHP_EOL) && substr_compare($line, PHP_EOL, -strlen(PHP_EOL), strlen(PHP_EOL), true) === 0) {
$line = substr($line, 0, -strlen(PHP_EOL));
}
return
$line;
}
up
-3
thflori
5 years ago
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");

?>
up
-5
Ixios
5 years ago
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
)
up
-3
mfuhrman at enetarch dot net
1 year ago
<?
/*
*
I've noticed strange behavior from readline while using it for user input from a CLI.

When I press multiple tabs it prints a scandir to the input stream.

Below is the code:
*
*/

$msg = "";
while ($msg != "quit")
{
while (($msg == "") || ($msg == "\r"))
$msg = readline ("> ");
}
?>
up
-8
roddric dot kasen at gmail dot com
8 years ago
<?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;*/

?>
up
-5
divinity76 at gmail dot com
2 years ago
<?php
/**
* readline() with unicode support
* php's builtin readline has dodgy unicode support, it only works
* with the correct environment locale settings, it doesn't seem to work at Cygwin (strips æøåÆØÅ),
* and it has historically had bugs like https://bugs.php.net/bug.php?id=81598
* meanwhile this readline has consistent unicode support across all platforms (including Cygwin)
* and doesn't care about locale settings.
*
* @param string $prompt
* @return string|false
*/
function readline_with_unicode_support(?string $prompt = null)/*: string|false*/
{
if (
$prompt !== null && $prompt !== '') {
echo
$prompt;
}
$line = fgets(STDIN);
// readline() removes the trailing newline, fgets() does not,
// to emulate the real readline(), we also need to remove it
if ($line !== false && strlen($line) >= strlen(PHP_EOL) && substr_compare($line, PHP_EOL, -strlen(PHP_EOL)) === 0) {
$line = substr($line, 0, -strlen(PHP_EOL));
}
return
$line;
}
To Top