У Laravel 13 з'явилася нова команда artisan dev, яка стандартизує все необхідне для роботи над проєктом: сервер розробки, воркер черг, вивід логів, Vite тощо. Донедавна скелет додатка пов'язував ці інструменти через скрипт dev у composer.json, який запускав чотири команди за допомогою npx concurrently.
Laravel 13.16 замінив це нативною командою:
php artisan dev
Скрипт composer dev все ще присутній у структурі проєкту, але тепер він лише викликає php artisan dev. Керування процесами перемістилося в PHP, де ви можете реєструвати власні процеси за допомогою класу DevCommands.
# Налаштування за замовчуванням
«З коробки» команда запускає чотири процеси:
| Назва | Команда |
|---|---|
server |
php artisan serve --host=localhost |
queue |
php artisan queue:listen --tries=1 --timeout=0 |
logs |
php artisan pail --timeout=0 |
vite |
npm run dev |
Процес Pail реєструється лише за наявності функції pcntl_fork, тому користувачі Windows отримують лише три інші процеси. Процес vite автоматично підбирає префікс залежно від lock-файлу у вашому проєкті (npm, pnpm, Yarn або Bun), тому в pnpm-проєкті він запустить pnpm run dev без жодних налаштувань. «Під капотом» команда все ще використовує concurrently, а з версії 13.18 вона передає прапорець --kill-others-on-fail. Це означає, що падіння одного процесу зупинить усі інші, не залишаючи систему в напівробочому стані.
# Реєстрація власних процесів
Стандартні налаштування підходять для нового проєкту, але додатки швидко ростуть. Наприклад, якщо ваш застосунок використовує Horizon замість queue:listen, працює з трансляціями через Reverb, приймає вебхуки Stripe через Stripe CLI та перевіряє типи TypeScript. Усе це можна зареєструвати в методі boot вашого AppServiceProvider:
namespace App\Providers;
use Illuminate\Foundation\DevCommands;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot(): void
{
if (! $this->app->environment('local')) {
return;
}
DevCommands::artisan('horizon', 'queue');
DevCommands::artisan('reverb:start --debug', 'reverb')->purple();
DevCommands::register(
'stripe listen --forward-to '.config('app.url').'/stripe/webhook',
'stripe'
)->orange();
DevCommands::nodeExec('tsc --noEmit --watch --preserveWatchOutput', 'types')->yellow();
}
}
Для реєстрації доступні чотири методи. Метод artisan() додає до команди префікс php artisan, node() використовує команду запуску пакетного менеджера, nodeExec() застосовує команду виконання (наприклад, npx), а register() приймає довільну shell-команду для всього іншого (як-от Stripe CLI у прикладі вище).
Другий аргумент — це назва процесу, що відображається в терміналі. Якщо його не вказати, назвою стане перше слово команди. Проте в прикладі назва queue не просто позначає процес: реєстрація процесу з таким ім'ям замінює стандартний воркер queue:listen на Horizon. Назви є ідентифікаторами процесів, тому їхнє повторне використання дозволяє замінювати або перевизначати стандартні команди:
DevCommands::artisan('serve --host=localhost --port=9000', 'server');
Порядок реєстрації не має значення. Команди вашого додатка завжди мають пріоритет над стандартними командами фреймворку, а ті — над командами з vendor. Таким чином, встановлений пакет не зможе непомітно замінити визначений вами процес.
Вибір кольорів опціональний. Кожен процес отримує свій колір автоматично, але ви можете використати blue(), purple(), pink(), orange(), green(), yellow() або color('#ff6347'), щоб виділити конкретний процес.
# Перегляд та фільтрація списку
Щоб побачити список зареєстрованих процесів без їхнього запуску, скористайтеся командою php artisan dev:list (додана в 13.17). Вона виводить кожен процес, його команду, а також файл і рядок, де він був зареєстрований — це корисно, якщо ви забули, звідки з'явилася та чи інша команда після встановлення пакетів.
Ви також можете відфільтрувати список, не видаляючи реєстрації:
// Запускати лише процеси server та vite...
DevCommands::only('server', 'vite');
// Запускати все, крім черг...
DevCommands::except('queue');
Обидва фільтри застосовуються під час виконання, тому процес, виключений через except(), все одно відображатиметься у вашому провайдері, і його можна буде легко повернути, видаливши лише один рядок.
Команду dev створив Joe Tannenbaum у Pull Request #60412. Детальніше про неї можна дізнатися в документації Artisan.