Readline add history: примеры (PHP)

Использование readline_add_history для управления историей ввода
Раздел: Ввод данных
readline_add_history(string $prompt): bool
Функция readline_add_history

Функция readline_add_history является частью модуля Readline в PHP. Она используется для добавления строки в историю ввода. История сохраняется между вызовами скрипта в рамках одной сессии интерпретатора, если используется встроенный CLI-сервер или интерактивный режим.

Эта функция применяется в интерактивных командных строковых (CLI) приложениях на PHP для запоминания ранее введённых команд или данных, что позволяет пользователю перемещаться по ним с помощью клавиш со стрелками вверх и вниз.

Аргументы функции

Функция принимает один обязательный параметр:

  • string $line - Строка, которую необходимо добавить в историю. Строка должна заканчиваться на новой строке, как правило, это пользовательский ввод, полученный через readline().

Функция возвращает true в случае успешного выполнения.

Краткие примеры использования
Пример 1: Базовое добавление в историю
<?php
// Включаем поддержку readline, если не включена автоматически
if (!function_exists('readline')) {
    dl('readline.so'); // Для Unix-систем, может потребоваться
}

$command = readline('Введите команду: ');
readline_add_history($command);
echo 'Команда добавлена в историю.';
?>
Введите команду: echo 'Hello'
Команда добавлена в историю.
Пример 2: Добавление нескольких строк
<?php
$inputs = [];
for ($i = 0; $i < 3; $i++) {
    $input = readline('Элемент ' . ($i+1) . ': ');
    $inputs[] = $input;
    readline_add_history($input);
}
echo 'Введённые данные: ' . implode(', ', $inputs);
?>
Элемент 1: Apple
Элемент 2: Banana
Элемент 3: Cherry
Введённые данные: Apple, Banana, Cherry
Похожие функции в PHP

Прямых аналогов readline_add_history в стандартной библиотеке PHP нет, так как она специфична для модуля Readline. Однако для чтения ввода в CLI-среде можно использовать:

  • fgets(STDIN) - Читает строку из стандартного ввода. Не поддерживает историю, автодополнение или управляющие последовательности. Подходит для простейшего ввода.
  • stream_get_line(STDIN, length, "\n") - Более контролируемое чтение строки из потока.
  • Библиотеки вроде "php-school/cli-menu" - Предоставляют полноценные интерактивные меню с историей и другими функциями, но требуют установки.

readline_add_history предпочтительнее, когда нужна именно история ввода в нативном интерактивном CLI-приложении без сторонних зависимостей.

Аналоги в других языках
Python: readline.add_history
import readline
command = input('Введите команду: ')
readline.add_history(command)
print(f'Добавлено: {command}')
Введите команду: import os
Добавлено: import os

В Python модуль readline предоставляет почти идентичный интерфейс. Он часто доступен по умолчанию в Unix-подобных системах.

JavaScript (Node.js): readline.createInterface и .history
const readline = require('readline');
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  historySize: 50
});
rl.question('Введите что-то: ', (answer) => {
  // История управляется автоматически интерфейсом
  console.log(`Вы ввели: ${answer}`);
  console.log('История:', rl.history);
  rl.close();
});
Введите что-то: console.log(1)
Вы ввели: console.log(1)
История: [ 'console.log(1)' ]

В Node.js история обычно управляется автоматически объектом интерфейса readline, но можно получить к ней доступ через свойство .history.

MySQL: Нет прямой аналогии

В MySQL нет встроенной истории ввода на уровне функций языка, так как это СУБД. История команд обычно предоставляется клиентским приложением (например, mysql cli, который использует GNU Readline или libedit).

Типичные ошибки
Ошибка 1: Функция недоступна
<?php
// Если модуль readline не установлен или отключён
$line = 'test';
$result = @readline_add_history($line);
if (!$result && !function_exists('readline_add_history')) {
    echo 'Ошибка: Модуль readline не доступен.';
}
?>
Ошибка: Модуль readline не доступен.
Ошибка 2: Передача нестрокового аргумента
<?php
// PHP 8 выдаст TypeError
readline_add_history(12345);
?>
Fatal error: Uncaught TypeError: readline_add_history(): Argument #1 ($line) must be of type string, int given...
Ошибка 3: Использование вне CLI SAPI
<?php
// При запуске через веб-сервер (не CLI)
if (php_sapi_name() !== 'cli') {
    die('Эта функция работает только в CLI-режиме.');
}
readline_add_history('test');
?>
Эта функция работает только в CLI-режиме.
Изменения в версиях PHP

Для функции readline_add_history значительных изменений в поведении в последних основных версиях PHP (5.x, 7.x, 8.x) не зафиксировано. Основные относящиеся к модулю изменения:

  • PHP 8.0.0: Параметр $line теперь имеет явный тип string. Передача нестрокового значения вызывает TypeError. Ранее неявное преобразование типов могло приводить к неожиданным результатам.
  • PHP 5.1.0: Модуль Readline был обновлён для использования библиотеки libedit. Совместимость с GNU Readline сохраняется, но некоторые расширенные возможности могут отличаться.

Рекомендуется всегда проверять доступность модуля, особенно в кросс-платформенных проектах.

Расширенные примеры
Пример 1: Интерактивный цикл с сохранением истории и выходом по команде
Пример php
<?php
$historyFile = sys_get_temp_dir() . '/php_readline_history.txt';
// Загружаем историю из файла, если существует
if (file_exists($historyFile)) {
    readline_read_history($historyFile);
}

while (true) {
    $line = readline('> ');
    if ($line === 'exit') {
        break;
    }
    if (trim($line) !== '') {
        readline_add_history($line);
        echo 'Вы сказали: ' . $line . PHP_EOL;
    }
}
// Сохраняем историю в файл
readline_write_history($historyFile);
echo 'История сохранена. До свидания!' . PHP_EOL;
?>
> echo 1
Вы сказали: echo 1
> $a = 10
Вы сказали: $a = 10
> exit
История сохранена. До свидания!
Пример 2: Фильтрация перед добавлением в историю
Пример php
<?php
function addToHistoryIfValid($line) {
    // Не добавляем пустые строки или команды, начинающиеся с пробела
    if (trim($line) === '' || strpos($line, ' ') === 0) {
        return false;
    }
    return readline_add_history($line);
}

$input = readline('Введите команду (пробелы в начале игнорируются): ');
if (addToHistoryIfValid($input)) {
    echo 'Добавлено.';
} else {
    echo 'Не добавлено (фильтр).';
}
?>
Введите команду (пробелы в начале игнорируются):   secret
Не добавлено (фильтр).
Пример 3: Интеграция с автодополнением и чтением истории
Пример php
<?php
// Функция автодополнения
function autoComplete($partial, $index) {
    $commands = ['list', 'delete', 'update', 'exit', 'help'];
    return $commands[$index] ?? null;
}

readline_completion_function('autoComplete');

// Добавляем несколько команд в историю для демонстрации
readline_add_history('list');
readline_add_history('help');

$cmd = readline('Команда (попробуйте нажать Tab): ');
readline_add_history($cmd);
echo 'Выполняем: ' . $cmd . PHP_EOL;

// Показать всю текущую историю
$hist = readline_list_history();
echo 'Текущая история: ' . implode(', ', $hist);
?>
Команда (попробуйте нажать Tab): li<Tab> // Пользователь нажимает Tab
Команда (попробуйте нажать Tab): list // Автодополнение
Выполняем: list
Текущая история: list, help, list

PHP readline_add_history function comments

En
Readline add history Adds a line to the history