Prompts
Вступ
Laravel Prompts - це PHP-пакет для додавання гарних і зручних форм до ваших консольних застосунків, з можливостями як у браузері - зокрема текстом-підказкою та валідацією.
Laravel Prompts чудово пасує для отримання вводу користувача у ваших консольних командах Artisan, але його можна використовувати і в будь-якому консольному проєкті на PHP.
Laravel Prompts підтримує macOS, Linux і Windows із WSL. Докладніше читайте в нашій документації про непідтримувані середовища та запасні варіанти.
Встановлення
Laravel Prompts уже входить до останнього випуску Laravel.
Laravel Prompts можна також встановити в інші ваші проєкти на PHP через менеджер пакетів Composer:
composer require laravel/prompts
Доступні промпти
Text
Функція text поставить користувачеві задане запитання, прийме його ввід і поверне його:
use function Laravel\Prompts\text;
$name = text('What is your name?');
Ви також можете додати текст-підказку, значення за замовчуванням та інформаційну підказку:
$name = text(
label: 'What is your name?',
placeholder: 'E.g. Taylor Otwell',
default: $user?->name,
hint: 'This will be displayed on your profile.'
);
Обов'язкові значення
Якщо ви вимагаєте, щоб значення було введено, передайте аргумент required:
$name = text(
label: 'What is your name?',
required: true
);
Якщо ви хочете змінити повідомлення про помилку валідації, передайте рядок:
$name = text(
label: 'What is your name?',
required: 'Your name is required.'
);
Додаткова валідація
Нарешті, якщо ви хочете виконати додаткову логіку валідації, передайте замикання в аргумент validate:
$name = text(
label: 'What is your name?',
validate: fn (string $value) => match (true) {
strlen($value) < 3 => 'The name must be at least 3 characters.',
strlen($value) > 255 => 'The name must not exceed 255 characters.',
default => null
}
);
Замикання отримає введене значення й може повернути повідомлення про помилку або null, якщо валідація пройшла.
Або ж ви можете скористатися силою валідатора Laravel. Для цього передайте в аргумент validate масив з іменем атрибута та потрібними правилами валідації:
$name = text(
label: 'What is your name?',
validate: ['name' => 'required|max:255|unique:users']
);
Textarea
Функція textarea поставить користувачеві задане запитання, прийме його ввід через багаторядкове поле й поверне його:
use function Laravel\Prompts\textarea;
$story = textarea('Tell me a story.');
Ви також можете додати текст-підказку, значення за замовчуванням та інформаційну підказку:
$story = textarea(
label: 'Tell me a story.',
placeholder: 'This is a story about...',
hint: 'This will be displayed on your profile.'
);
Обов'язкові значення
Якщо ви вимагаєте, щоб значення було введено, передайте аргумент required:
$story = textarea(
label: 'Tell me a story.',
required: true
);
Якщо ви хочете змінити повідомлення про помилку валідації, передайте рядок:
$story = textarea(
label: 'Tell me a story.',
required: 'A story is required.'
);
Додаткова валідація
Нарешті, якщо ви хочете виконати додаткову логіку валідації, передайте замикання в аргумент validate:
$story = textarea(
label: 'Tell me a story.',
validate: fn (string $value) => match (true) {
strlen($value) < 250 => 'The story must be at least 250 characters.',
strlen($value) > 10000 => 'The story must not exceed 10,000 characters.',
default => null
}
);
Замикання отримає введене значення й може повернути повідомлення про помилку або null, якщо валідація пройшла.
Або ж ви можете скористатися силою валідатора Laravel. Для цього передайте в аргумент validate масив з іменем атрибута та потрібними правилами валідації:
$story = textarea(
label: 'Tell me a story.',
validate: ['story' => 'required|max:10000']
);
Number
Функція number поставить користувачеві задане запитання, прийме його числовий ввід і поверне його. Функція number дозволяє користувачеві змінювати число клавішами зі стрілками вгору й вниз:
use function Laravel\Prompts\number;
$number = number('How many copies would you like?');
Ви також можете додати текст-підказку, значення за замовчуванням та інформаційну підказку:
$name = number(
label: 'How many copies would you like?',
placeholder: '5',
default: 1,
hint: 'This will be determine how many copies to create.'
);
Обов'язкові значення
Якщо ви вимагаєте, щоб значення було введено, передайте аргумент required:
$copies = number(
label: 'How many copies would you like?',
required: true
);
Якщо ви хочете змінити повідомлення про помилку валідації, передайте рядок:
$copies = number(
label: 'How many copies would you like?',
required: 'A number of copies is required.'
);
Додаткова валідація
Нарешті, якщо ви хочете виконати додаткову логіку валідації, передайте замикання в аргумент validate:
$copies = number(
label: 'How many copies would you like?',
validate: fn (?int $value) => match (true) {
$value < 1 => 'At least one copy is required.',
$value > 100 => 'You may not create more than 100 copies.',
default => null
}
);
Замикання отримає введене значення й може повернути повідомлення про помилку або null, якщо валідація пройшла.
Або ж ви можете скористатися силою валідатора Laravel. Для цього передайте в аргумент validate масив з іменем атрибута та потрібними правилами валідації:
$copies = number(
label: 'How many copies would you like?',
validate: ['copies' => 'required|integer|min:1|max:100']
);
Password
Функція password схожа на функцію text, але ввід користувача маскується під час набору в консолі. Це стає в пригоді, коли ви запитуєте чутливу інформацію - як-от паролі:
use function Laravel\Prompts\password;
$password = password('What is your password?');
Ви також можете додати текст-підказку та інформаційну підказку:
$password = password(
label: 'What is your password?',
placeholder: 'password',
hint: 'Minimum 8 characters.'
);
Обов'язкові значення
Якщо ви вимагаєте, щоб значення було введено, передайте аргумент required:
$password = password(
label: 'What is your password?',
required: true
);
Якщо ви хочете змінити повідомлення про помилку валідації, передайте рядок:
$password = password(
label: 'What is your password?',
required: 'The password is required.'
);
Додаткова валідація
Нарешті, якщо ви хочете виконати додаткову логіку валідації, передайте замикання в аргумент validate:
$password = password(
label: 'What is your password?',
validate: fn (string $value) => match (true) {
strlen($value) < 8 => 'The password must be at least 8 characters.',
default => null
}
);
Замикання отримає введене значення й може повернути повідомлення про помилку або null, якщо валідація пройшла.
Або ж ви можете скористатися силою валідатора Laravel. Для цього передайте в аргумент validate масив з іменем атрибута та потрібними правилами валідації:
$password = password(
label: 'What is your password?',
validate: ['password' => 'min:8']
);
Confirm
Якщо вам треба запитати в користувача підтвердження «так чи ні», скористайтеся функцією confirm. Користувачі можуть скористатися клавішами зі стрілками або натиснути y чи n, щоб обрати відповідь. Ця функція поверне true або false.
use function Laravel\Prompts\confirm;
$confirmed = confirm('Do you accept the terms?');
Ви також можете додати значення за замовчуванням, власні написи для «Yes» і «No» та інформаційну підказку:
$confirmed = confirm(
label: 'Do you accept the terms?',
default: false,
yes: 'I accept',
no: 'I decline',
hint: 'The terms must be accepted to continue.'
);
Вимога відповіді «Yes»
За потреби ви можете зобов'язати користувачів обрати «Yes», передавши аргумент required:
$confirmed = confirm(
label: 'Do you accept the terms?',
required: true
);
Якщо ви хочете змінити повідомлення про помилку валідації, передайте рядок:
$confirmed = confirm(
label: 'Do you accept the terms?',
required: 'You must accept the terms to continue.'
);
Select
Якщо вам потрібно, щоб користувач обрав із наперед визначеного набору варіантів, скористайтеся функцією select:
use function Laravel\Prompts\select;
$role = select(
label: 'What role should the user have?',
options: ['Member', 'Contributor', 'Owner']
);
Ви також можете вказати варіант за замовчуванням та інформаційну підказку:
$role = select(
label: 'What role should the user have?',
options: ['Member', 'Contributor', 'Owner'],
default: 'Owner',
hint: 'The role may be changed at any time.'
);
Ви також можете передати в аргумент options асоціативний масив, щоб повертався ключ обраного варіанта, а не його значення:
$role = select(
label: 'What role should the user have?',
options: [
'member' => 'Member',
'contributor' => 'Contributor',
'owner' => 'Owner',
],
default: 'owner'
);
До п'яти варіантів буде показано, перш ніж список почне прокручуватися. Ви можете змінити це, передавши аргумент scroll:
$role = select(
label: 'Which category would you like to assign?',
options: Category::pluck('name', 'id'),
scroll: 10
);
Додаткова інформація
Аргумент info дозволяє показувати додаткову інформацію про поточний підсвічений варіант. Якщо передати замикання, воно отримає значення підсвіченого варіанта й має повернути рядок або null:
$role = select(
label: 'What role should the user have?',
options: [
'member' => 'Member',
'contributor' => 'Contributor',
'owner' => 'Owner',
],
info: fn (string $value) => match ($value) {
'member' => 'Can view and comment.',
'contributor' => 'Can view, comment, and edit.',
'owner' => 'Full access to all resources.',
default => null,
}
);
Ви також можете передати в аргумент info статичний рядок, якщо інформація не залежить від підсвіченого варіанта:
$role = select(
label: 'What role should the user have?',
options: ['Member', 'Contributor', 'Owner'],
info: 'The role may be changed at any time.'
);
Додаткова валідація
На відміну від інших функцій-промптів, функція select не приймає аргумент required, адже не обрати нічого неможливо. Проте ви можете передати замикання в аргумент validate, якщо вам треба показати варіант, але завадити його вибору:
$role = select(
label: 'What role should the user have?',
options: [
'member' => 'Member',
'contributor' => 'Contributor',
'owner' => 'Owner',
],
validate: fn (string $value) =>
$value === 'owner' && User::where('role', 'owner')->exists()
? 'An owner already exists.'
: null
);
Якщо аргумент options - асоціативний масив, замикання отримає обраний ключ, інакше - обране значення. Замикання може повернути повідомлення про помилку або null, якщо валідація пройшла.
Multi-select
Якщо вам потрібно, щоб користувач міг обрати кілька варіантів, скористайтеся функцією multiselect:
use function Laravel\Prompts\multiselect;
$permissions = multiselect(
label: 'What permissions should be assigned?',
options: ['Read', 'Create', 'Update', 'Delete']
);
Ви також можете вказати варіанти за замовчуванням та інформаційну підказку:
use function Laravel\Prompts\multiselect;
$permissions = multiselect(
label: 'What permissions should be assigned?',
options: ['Read', 'Create', 'Update', 'Delete'],
default: ['Read', 'Create'],
hint: 'Permissions may be updated at any time.'
);
Ви також можете передати в аргумент options асоціативний масив, щоб повертати ключі обраних варіантів, а не їхні значення:
$permissions = multiselect(
label: 'What permissions should be assigned?',
options: [
'read' => 'Read',
'create' => 'Create',
'update' => 'Update',
'delete' => 'Delete',
],
default: ['read', 'create']
);
До п'яти варіантів буде показано, перш ніж список почне прокручуватися. Ви можете змінити це, передавши аргумент scroll:
$categories = multiselect(
label: 'What categories should be assigned?',
options: Category::pluck('name', 'id'),
scroll: 10
);
Додаткова інформація
Аргумент info дозволяє показувати додаткову інформацію про поточний підсвічений варіант. Якщо передати замикання, воно отримає значення підсвіченого варіанта й має повернути рядок або null:
$permissions = multiselect(
label: 'What permissions should be assigned?',
options: [
'read' => 'Read',
'create' => 'Create',
'update' => 'Update',
'delete' => 'Delete',
],
info: fn (string $value) => match ($value) {
'read' => 'View resources and their properties.',
'create' => 'Create new resources.',
'update' => 'Modify existing resources.',
'delete' => 'Permanently remove resources.',
default => null,
}
);
Вимога значення
За замовчуванням користувач може обрати нуль чи більше варіантів. Ви можете передати аргумент required, щоб вимагати щонайменше один:
$categories = multiselect(
label: 'What categories should be assigned?',
options: Category::pluck('name', 'id'),
required: true
);
Якщо ви хочете змінити повідомлення про помилку валідації, передайте рядок в аргумент required:
$categories = multiselect(
label: 'What categories should be assigned?',
options: Category::pluck('name', 'id'),
required: 'You must select at least one category'
);
Додаткова валідація
Ви можете передати замикання в аргумент validate, якщо вам треба показати варіант, але завадити його вибору:
$permissions = multiselect(
label: 'What permissions should the user have?',
options: [
'read' => 'Read',
'create' => 'Create',
'update' => 'Update',
'delete' => 'Delete',
],
validate: fn (array $values) => ! in_array('read', $values)
? 'All users require the read permission.'
: null
);
Якщо аргумент options - асоціативний масив, замикання отримає обрані ключі, інакше - обрані значення. Замикання може повернути повідомлення про помилку або null, якщо валідація пройшла.
Suggest
Функція suggest дозволяє додати автодоповнення для можливих варіантів. Користувач і далі може ввести будь-яку відповідь, незалежно від підказок автодоповнення:
use function Laravel\Prompts\suggest;
$name = suggest('What is your name?', ['Taylor', 'Dayle']);
Або ж ви можете передати замикання другим аргументом до функції suggest. Замикання викликатиметься щоразу, коли користувач вводить символ. Воно має приймати рядковий параметр із уже введеним текстом і повертати масив варіантів для автодоповнення:
$name = suggest(
label: 'What is your name?',
options: fn ($value) => collect(['Taylor', 'Dayle'])
->filter(fn ($name) => Str::contains($name, $value, ignoreCase: true))
)
Ви також можете додати текст-підказку, значення за замовчуванням та інформаційну підказку:
$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
placeholder: 'E.g. Taylor',
default: $user?->name,
hint: 'This will be displayed on your profile.'
);
Додаткова інформація
Аргумент info дозволяє показувати додаткову інформацію про поточний підсвічений варіант. Якщо передати замикання, воно отримає значення підсвіченого варіанта й має повернути рядок або null:
$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
info: fn (string $value) => match ($value) {
'Taylor' => 'Administrator',
'Dayle' => 'Contributor',
default => null,
}
);
Обов'язкові значення
Якщо ви вимагаєте, щоб значення було введено, передайте аргумент required:
$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
required: true
);
Якщо ви хочете змінити повідомлення про помилку валідації, передайте рядок:
$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
required: 'Your name is required.'
);
Додаткова валідація
Нарешті, якщо ви хочете виконати додаткову логіку валідації, передайте замикання в аргумент validate:
$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
validate: fn (string $value) => match (true) {
strlen($value) < 3 => 'The name must be at least 3 characters.',
strlen($value) > 255 => 'The name must not exceed 255 characters.',
default => null
}
);
Замикання отримає введене значення й може повернути повідомлення про помилку або null, якщо валідація пройшла.
Або ж ви можете скористатися силою валідатора Laravel. Для цього передайте в аргумент validate масив з іменем атрибута та потрібними правилами валідації:
$name = suggest(
label: 'What is your name?',
options: ['Taylor', 'Dayle'],
validate: ['name' => 'required|min:3|max:255']
);
Search
Якщо у вас багато варіантів на вибір, функція search дозволяє користувачеві ввести пошуковий запит, щоб відфільтрувати результати, а вже потім обрати варіант клавішами зі стрілками:
use function Laravel\Prompts\search;
$id = search(
label: 'Search for the user that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: []
);
Замикання отримає текст, уже введений користувачем, і має повернути масив варіантів. Якщо ви повернете асоціативний масив, буде повернено ключ обраного варіанта, інакше - його значення.
Фільтруючи масив, коли ви маєте намір повертати значення, скористайтеся функцією array_values або методом колекції values, щоб масив не став асоціативним:
$names = collect(['Taylor', 'Abigail']);
$selected = search(
label: 'Search for the user that should receive the mail',
options: fn (string $value) => $names
->filter(fn ($name) => Str::contains($name, $value, ignoreCase: true))
->values()
->all(),
);
Ви також можете додати текст-підказку та інформаційну підказку:
$id = search(
label: 'Search for the user that should receive the mail',
placeholder: 'E.g. Taylor Otwell',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
hint: 'The user will receive an email immediately.'
);
До п'яти варіантів буде показано, перш ніж список почне прокручуватися. Ви можете змінити це, передавши аргумент scroll:
$id = search(
label: 'Search for the user that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
scroll: 10
);
Додаткова інформація
Аргумент info дозволяє показувати додаткову інформацію про поточний підсвічений варіант. Якщо передати замикання, воно отримає значення підсвіченого варіанта й має повернути рядок або null:
$id = search(
label: 'Search for the user that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
info: fn (int $userId) => User::find($userId)?->email
);
Додаткова валідація
Якщо ви хочете виконати додаткову логіку валідації, передайте замикання в аргумент validate:
$id = search(
label: 'Search for the user that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
validate: function (int|string $value) {
$user = User::findOrFail($value);
if ($user->opted_out) {
return 'This user has opted-out of receiving mail.';
}
}
);
Якщо замикання options повертає асоціативний масив, замикання валідації отримає обраний ключ, інакше - обране значення. Замикання може повернути повідомлення про помилку або null, якщо валідація пройшла.
Multi-search
Якщо у вас багато варіантів для пошуку й користувачеві треба обрати кілька, функція multisearch дозволяє ввести пошуковий запит, щоб відфільтрувати результати, а вже потім обрати варіанти клавішами зі стрілками й пробілом:
use function Laravel\Prompts\multisearch;
$ids = multisearch(
'Search for users who should receive the mail',
fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: []
);
Замикання отримає текст, уже введений користувачем, і має повернути масив варіантів. Якщо ви повернете асоціативний масив, буде повернено ключі обраних варіантів; інакше - їхні значення.
Фільтруючи масив, коли ви маєте намір повертати значення, скористайтеся функцією array_values або методом колекції values, щоб масив не став асоціативним:
$names = collect(['Taylor', 'Abigail']);
$selected = multisearch(
label: 'Search for users who should receive the mail',
options: fn (string $value) => $names
->filter(fn ($name) => Str::contains($name, $value, ignoreCase: true))
->values()
->all(),
);
Ви також можете додати текст-підказку та інформаційну підказку:
$ids = multisearch(
label: 'Search for users who should receive the mail',
placeholder: 'E.g. Taylor Otwell',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
hint: 'The user will receive an email immediately.'
);
До п'яти варіантів буде показано, перш ніж список почне прокручуватися. Ви можете змінити це, передавши аргумент scroll:
$ids = multisearch(
label: 'Search for the users that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
scroll: 10
);
Додаткова інформація
Аргумент info дозволяє показувати додаткову інформацію про поточний підсвічений варіант. Якщо передати замикання, воно отримає значення підсвіченого варіанта й має повернути рядок або null:
$ids = multisearch(
label: 'Search for the users that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
info: fn (int $userId) => User::find($userId)?->email
);
Вимога значення
За замовчуванням користувач може обрати нуль чи більше варіантів. Ви можете передати аргумент required, щоб вимагати щонайменше один:
$ids = multisearch(
label: 'Search for the users that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
required: true
);
Якщо ви хочете змінити повідомлення про помилку валідації, передайте рядок в аргумент required:
$ids = multisearch(
label: 'Search for the users that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
required: 'You must select at least one user.'
);
Додаткова валідація
Якщо ви хочете виконати додаткову логіку валідації, передайте замикання в аргумент validate:
$ids = multisearch(
label: 'Search for the users that should receive the mail',
options: fn (string $value) => strlen($value) > 0
? User::whereLike('name', "%{$value}%")->pluck('name', 'id')->all()
: [],
validate: function (array $values) {
$optedOut = User::whereLike('name', '%a%')->findMany($values);
if ($optedOut->isNotEmpty()) {
return $optedOut->pluck('name')->join(', ', ', and ').' have opted out.';
}
}
);
Якщо замикання options повертає асоціативний масив, замикання валідації отримає обрані ключі; інакше - обрані значення. Замикання може повернути повідомлення про помилку або null, якщо валідація пройшла.
Pause
Функція pause дозволяє показати користувачеві інформаційний текст і зачекати, доки він підтвердить бажання рухатися далі, натиснувши клавішу Enter / Return:
use function Laravel\Prompts\pause;
pause('Press ENTER to continue.');
Autocomplete
Функція autocomplete дозволяє додати вбудоване автодоповнення для можливих варіантів. Поки користувач набирає текст, підказки, що відповідають його вводу, з'являтимуться як примарний текст, який можна прийняти натисканням Tab чи стрілки вправо:
use function Laravel\Prompts\autocomplete;
$name = autocomplete(
label: 'What is your name?',
options: ['Taylor', 'Dayle', 'Jess', 'Nuno', 'Tim']
);
Ви також можете додати текст-підказку, значення за замовчуванням та інформаційну підказку:
$name = autocomplete(
label: 'What is your name?',
options: ['Taylor', 'Dayle', 'Jess', 'Nuno', 'Tim'],
placeholder: 'E.g. Taylor',
default: $user?->name,
hint: 'Use tab to accept, up/down to cycle.'
);
Динамічні варіанти
Ви також можете передати замикання, щоб динамічно генерувати варіанти за вводом користувача. Замикання викликатиметься щоразу, коли користувач вводить символ, і має повертати масив варіантів для автодоповнення:
$file = autocomplete(
label: 'Which file?',
options: fn (string $value) => collect($files)
->filter(fn ($file) => str_starts_with(strtolower($file), strtolower($value)))
->values()
->all(),
);
Обов'язкові значення
Якщо ви вимагаєте, щоб значення було введено, передайте аргумент required:
$name = autocomplete(
label: 'What is your name?',
options: ['Taylor', 'Dayle', 'Jess', 'Nuno', 'Tim'],
required: true
);
Якщо ви хочете змінити повідомлення про помилку валідації, передайте рядок:
$name = autocomplete(
label: 'What is your name?',
options: ['Taylor', 'Dayle', 'Jess', 'Nuno', 'Tim'],
required: 'Your name is required.'
);
Додаткова валідація
Нарешті, якщо ви хочете виконати додаткову логіку валідації, передайте замикання в аргумент validate:
$name = autocomplete(
label: 'What is your name?',
options: ['Taylor', 'Dayle', 'Jess', 'Nuno', 'Tim'],
validate: fn (string $value) => match (true) {
strlen($value) < 3 => 'The name must be at least 3 characters.',
strlen($value) > 255 => 'The name must not exceed 255 characters.',
default => null
}
);
Замикання отримає введене значення й може повернути повідомлення про помилку або null, якщо валідація пройшла.
Перетворення вводу перед валідацією
Іноді вам може знадобитися перетворити ввід промпту, перш ніж відбудеться валідація. Наприклад, ви можете захотіти прибрати пробіли з переданих рядків. Для цього багато функцій-промптів надають аргумент transform, який приймає замикання:
$name = text(
label: 'What is your name?',
transform: fn (string $value) => trim($value),
validate: fn (string $value) => match (true) {
strlen($value) < 3 => 'The name must be at least 3 characters.',
strlen($value) > 255 => 'The name must not exceed 255 characters.',
default => null
}
);
Форми
Часто у вас буде кілька промптів, які показуються послідовно, щоб зібрати інформацію перед подальшими діями. Ви можете скористатися функцією form, щоб створити згрупований набір промптів для заповнення:
use function Laravel\Prompts\form;
$responses = form()
->text('What is your name?', required: true)
->password('What is your password?', validate: ['password' => 'min:8'])
->confirm('Do you accept the terms?')
->submit();
Метод submit поверне масив із числовими індексами, що містить усі відповіді з промптів форми. Проте ви можете дати кожному промпту ім'я через аргумент name. Коли ім'я задано, до відповіді цього промпту можна звертатися за цим іменем:
use App\Models\User;
use function Laravel\Prompts\form;
$responses = form()
->text('What is your name?', required: true, name: 'name')
->password(
label: 'What is your password?',
validate: ['password' => 'min:8'],
name: 'password'
)
->confirm('Do you accept the terms?')
->submit();
User::create([
'name' => $responses['name'],
'password' => $responses['password'],
]);
Головна перевага функції form - можливість повернутися до попередніх промптів форми через CTRL + U. Це дозволяє користувачеві виправити помилки чи змінити вибір, не скасовуючи й не починаючи форму заново.
Якщо вам потрібен тонший контроль над промптом у формі, викличте метод add замість того, щоб напряму викликати одну з функцій-промптів. Методу add передаються всі попередні відповіді користувача:
use function Laravel\Prompts\form;
use function Laravel\Prompts\outro;
use function Laravel\Prompts\text;
$responses = form()
->text('What is your name?', required: true, name: 'name')
->add(function ($responses) {
return text("How old are you, {$responses['name']}?");
}, name: 'age')
->submit();
outro("Your name is {$responses['name']} and you are {$responses['age']} years old.");
Інформаційні повідомлення
Функції note, info, warning, error та alert дозволяють показувати інформаційні повідомлення:
use function Laravel\Prompts\info;
info('Package installed successfully.');
Виноски
Функція callout показує повідомлення в рамці із заголовком і вмістом. Виноски стають у пригоді, щоб показати важливу інформацію, яка має вирізнятися, - як-от підсумки розгортання, деталі помилок чи оновлення статусу:
use function Laravel\Prompts\callout;
callout(
label: 'Environment Configured',
content: 'Your application is running in production mode with 4 workers.',
);
Ви можете передати warning чи error в аргумент type, щоб змінити візуальний стиль виноски:
callout(
label: 'Deprecation Notice',
content: 'The `--prefer-stable` flag will be removed in v4.0. Use `--stability=stable` instead.',
type: 'warning',
);
callout(
label: 'Database Connection Failed',
content: 'Could not connect to MySQL on 127.0.0.1:3306.',
type: 'error',
);
Аргумент info додає до виноски рядок-підвал, що стає в пригоді для показу метаданих на кшталт ID чи часових міток:
callout(
label: 'Deployment Summary',
content: 'Your application was deployed to production.',
info: 'deploy-id: d4f8a2c',
);
Насичений вміст
Замість рядка ви можете передати масив рядків та елементів, щоб побудувати насичені структуровані виноски. Клас Element надає фабричні методи для створення заголовків, марковані та нумеровані списки, списки «ключ - значення» та посилання:
use Laravel\Prompts\Elements\Element;
use function Laravel\Prompts\callout;
callout('Deployment Summary', [
'Your application was deployed to production at 2024-03-15 14:32 UTC.',
Element::heading('What Changed'),
Element::bulletedList([
'Migrated 3 pending database migrations',
'Cleared and rebuilt route cache',
'Restarted 4 queue workers',
]),
Element::heading('Next Steps'),
Element::numberedList([
'Verify the health check endpoint at /up',
'Monitor error rates for the next 15 minutes',
'Confirm background jobs are processing',
]),
]);
Ви також можете скористатися Element::keyValueList, щоб показати дані з підписами:
callout('Database Connection Failed', [
'Could not connect to the database server.',
Element::keyValueList([
'Host' => '127.0.0.1',
'Port' => '3306',
'Database' => 'forge',
'Status' => 'Connection refused',
]),
], type: 'error');
Метод Element::link створює клікабельне гіперпосилання в терміналах, які підтримують OSC 8. Ви можете передати сам URL або URL із власним підписом:
callout('Server Health Check', [
'Multiple services are reporting degraded performance.',
Element::heading('Affected Services'),
'Look here: '.Element::link('https://example.com/health', 'Health Dashboard'),
Element::link('https://example.com/health'),
]);
Якщо підпис не задано, як текст посилання буде показано сам URL.
Таблиці
Функція table дозволяє легко показати кілька рядків і стовпців даних. Усе, що вам треба, - передати імена стовпців і дані таблиці:
use function Laravel\Prompts\table;
table(
headers: ['Name', 'Email'],
rows: User::all(['name', 'email'])->toArray()
);
Spin
Функція spin показує спінер разом із необов'язковим повідомленням, доки виконується заданий колбек. Вона слугує індикатором тривалих процесів і повертає результати колбека після завершення:
use function Laravel\Prompts\spin;
$response = spin(
callback: fn () => Http::get('http://example.com'),
message: 'Fetching response...'
);
Функція
spinвимагає розширення PHP PCNTL, щоб анімувати спінер. Коли це розширення недоступне, натомість з'явиться статична версія спінера.
Індикатори прогресу
Для тривалих завдань буває корисно показати індикатор прогресу, який повідомляє користувачам, наскільки завдання виконане. За допомогою функції progress Laravel покаже індикатор прогресу й просуватиме його на кожній ітерації по заданому ітерабельному значенню:
use function Laravel\Prompts\progress;
$users = progress(
label: 'Updating users',
steps: User::all(),
callback: fn ($user) => $this->performTask($user)
);
Функція progress працює як функція map і поверне масив із результатами кожної ітерації вашого колбека.
Колбек може також приймати екземпляр Laravel\Prompts\Progress, що дозволяє змінювати підпис і підказку на кожній ітерації:
$users = progress(
label: 'Updating users',
steps: User::all(),
callback: function ($user, $progress) {
$progress
->label("Updating {$user->name}")
->hint("Created on {$user->created_at}");
return $this->performTask($user);
},
hint: 'This may take some time.'
);
Іноді вам може знадобитися ручніший контроль над просуванням індикатора. Спершу задайте загальну кількість кроків, які пройде процес. Далі просувайте індикатор методом advance після обробки кожного елемента:
$progress = progress(label: 'Updating users', steps: 10);
$users = User::all();
$progress->start();
foreach ($users as $user) {
$this->performTask($user);
$progress->advance();
}
$progress->finish();
Task
Функція task показує підписане завдання зі спінером і прокручуваною областю живого виводу, доки виконується заданий колбек. Вона ідеальна, щоб обгорнути тривалі процеси - як-от встановлення залежностей чи скрипти розгортання, - даючи змогу бачити в реальному часі, що відбувається:
use function Laravel\Prompts\task;
task(
label: 'Installing dependencies',
callback: function ($logger) {
// Long-running process...
}
);
Колбек отримує екземпляр Logger, яким ви можете показувати рядки логу, повідомлення про статус і потоковий текст в області виводу завдання.
Функція
taskвимагає розширення PHP PCNTL, щоб анімувати спінер. Коли це розширення недоступне, натомість з'явиться статична версія завдання.
Запис рядків логу
Метод line пише один рядок логу до прокручуваної області виводу завдання:
task(
label: 'Installing dependencies',
callback: function ($logger) {
$logger->line('Resolving packages...');
// ...
$logger->line('Downloading laravel/framework');
// ...
}
);
Повідомлення про статус
Ви можете скористатися методами success, warning та error, щоб показувати повідомлення про статус. Вони з'являються як стабільні підсвічені повідомлення над прокручуваною областю логу:
task(
label: 'Deploying application',
callback: function ($logger) {
$logger->line('Pulling latest changes...');
// ...
$logger->success('Changes pulled!');
$logger->line('Running migrations...');
// ...
$logger->warning('No new migrations to run.');
$logger->line('Clearing cache...');
// ...
$logger->success('Cache cleared!');
}
);
Оновлення підпису
Метод label дозволяє оновлювати підпис завдання, доки воно виконується:
task(
label: 'Starting deployment...',
callback: function ($logger) {
$logger->label('Pulling latest changes...');
// ...
$logger->label('Running migrations...');
// ...
$logger->label('Clearing cache...');
// ...
}
);
Показ підпідпису
Метод subLabel показує притлумлений рядок під головним підписом завдання, що стає в пригоді, щоб повідомляти тимчасовий статус - як-от крок, який виконується зараз. Передайте порожній рядок, щоб очистити підпідпис:
task(
label: 'Deploying',
callback: function ($logger) {
$logger->subLabel('Building assets...');
// ...
$logger->subLabel('Running migrations...');
// ...
$logger->subLabel('');
}
);
Ви також можете задати початковий підпідпис через аргумент subLabel:
task(
label: 'Deploying',
callback: function ($logger) {
// ...
},
subLabel: 'Preparing...'
);
Потоковий текст
Для процесів, які видають вивід поступово - як-от згенеровані AI відповіді, - метод partial дозволяє транслювати текст слово за словом чи порція за порцією. Коли потік завершено, викличте commitPartial, щоб фіналізувати вивід:
task(
label: 'Generating response...',
callback: function ($logger) {
foreach ($words as $word) {
$logger->partial($word . ' ');
}
$logger->commitPartial();
}
);
Налаштування ліміту виводу
За замовчуванням завдання показує до 10 рядків прокручуваного виводу. Ви можете змінити це через аргумент limit:
task(
label: 'Installing dependencies',
callback: function ($logger) {
// ...
},
limit: 20
);
Збереження підсумку
За замовчуванням вивід завдання стирається, щойно колбек завершується. Якщо ви хочете лишити повідомлення про статус на екрані після завершення завдання, передайте аргумент keepSummary:
task(
label: 'Deploying',
callback: function ($logger) {
$logger->success('Assets built');
// ...
$logger->success('Migrations complete');
},
keepSummary: true,
);
Stream
Функція stream показує текст, який транслюється в термінал, - ідеально для показу згенерованого AI вмісту чи будь-якого тексту, що надходить поступово:
use function Laravel\Prompts\stream;
$stream = stream();
foreach ($words as $word) {
$stream->append($word . ' ');
usleep(25_000); // Simulate delay between chunks...
}
$stream->close();
Метод append додає текст до потоку, рендерячи його з ефектом поступової появи. Коли весь вміст передано, викличте метод close, щоб фіналізувати вивід і повернути курсор.
Заголовок термінала
Функція title оновлює заголовок вікна чи вкладки термінала користувача:
use function Laravel\Prompts\title;
title('Installing Dependencies');
Щоб скинути заголовок термінала до стандартного, передайте порожній рядок:
title('');
Очищення термінала
Функція clear дозволяє очистити термінал користувача:
use function Laravel\Prompts\clear;
clear();
Що врахувати щодо термінала
Ширина термінала
Якщо довжина будь-якого підпису, варіанта чи повідомлення про помилку валідації перевищує кількість «стовпців» у терміналі користувача, її буде автоматично обрізано. Подумайте про скорочення цих рядків, якщо ваші користувачі можуть працювати у вузьких терміналах. Зазвичай безпечна максимальна довжина - 74 символи, щоб підтримати 80-символьний термінал.
Висота термінала
Для будь-яких промптів, що приймають аргумент scroll, задане значення буде автоматично зменшено під висоту термінала користувача - з урахуванням місця для повідомлення про помилку валідації.
Непідтримувані середовища та запасні варіанти
Laravel Prompts підтримує macOS, Linux і Windows із WSL. Через обмеження Windows-версії PHP наразі неможливо користуватися Laravel Prompts у Windows поза WSL.
Тому Laravel Prompts підтримує запасний варіант з альтернативною реалізацією - як-от Symfony Console Question Helper.
Коли ви користуєтеся Laravel Prompts разом із фреймворком Laravel, запасні варіанти для кожного промпту вже налаштовані за вас і автоматично вмикатимуться в непідтримуваних середовищах.
Умови запасного варіанта
Якщо ви не користуєтеся Laravel або хочете налаштувати, коли саме застосовується запасна поведінка, передайте булеве значення статичному методу fallbackWhen класу Prompt:
use Laravel\Prompts\Prompt;
Prompt::fallbackWhen(
! $input->isInteractive() || windows_os() || app()->runningUnitTests()
);
Запасна поведінка
Якщо ви не користуєтеся Laravel або хочете налаштувати запасну поведінку, передайте замикання статичному методу fallbackUsing кожного класу промпту:
use Laravel\Prompts\TextPrompt;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Style\SymfonyStyle;
TextPrompt::fallbackUsing(function (TextPrompt $prompt) use ($input, $output) {
$question = (new Question($prompt->label, $prompt->default ?: null))
->setValidator(function ($answer) use ($prompt) {
if ($prompt->required && $answer === null) {
throw new \RuntimeException(
is_string($prompt->required) ? $prompt->required : 'Required.'
);
}
if ($prompt->validate) {
$error = ($prompt->validate)($answer ?? '');
if ($error) {
throw new \RuntimeException($error);
}
}
return $answer;
});
return (new SymfonyStyle($input, $output))
->askQuestion($question);
});
Запасні варіанти треба налаштовувати окремо для кожного класу промпту. Замикання отримає екземпляр класу промпту й має повернути тип, відповідний для цього промпту.
Тестування
Laravel надає різні методи, щоб перевірити, що ваша команда показує очікувані повідомлення Prompts:
test('report generation', function () {
$this->artisan('report:generate')
->expectsPromptsInfo('Welcome to the application!')
->expectsPromptsWarning('This action cannot be undone')
->expectsPromptsError('Something went wrong')
->expectsPromptsAlert('Important notice!')
->expectsPromptsIntro('Starting process...')
->expectsPromptsOutro('Process completed!')
->expectsPromptsTable(
headers: ['Name', 'Email'],
rows: [
['Taylor Otwell', 'taylor@example.com'],
['Jason Beggs', 'jason@example.com'],
]
)
->assertExitCode(0);
});
public function test_report_generation(): void
{
$this->artisan('report:generate')
->expectsPromptsInfo('Welcome to the application!')
->expectsPromptsWarning('This action cannot be undone')
->expectsPromptsError('Something went wrong')
->expectsPromptsAlert('Important notice!')
->expectsPromptsIntro('Starting process...')
->expectsPromptsOutro('Process completed!')
->expectsPromptsTable(
headers: ['Name', 'Email'],
rows: [
['Taylor Otwell', 'taylor@example.com'],
['Jason Beggs', 'jason@example.com'],
]
)
->assertExitCode(0);
}