Игнорировать пользовательскую команду Laravel Artisan на производстве

Я написал пользовательскую команду Artisan (назовем ее MyDusk.php), которая расширяет/абстрагирует некоторые функции базовой команды Dusk.

Эта пользовательская команда расширяет Laravel\Dusk\Console\DuskCommand из пакета Dusk.

Проблема в том, что на производстве пакет Dusk не установлен (он находится под require-dev в composer.json)

Поэтому, когда композитор создает свои файлы автозагрузки на производстве, он выдает ошибку, когда доходит до MyDusk.php, потому что не может найти Laravel\Dusk\Console\DuskCommand.

PHP Fatal error:  Class 'Laravel\Dusk\Console\DuskCommand' not found in app/Console/Commands/Dusk.php on line 10

In Dusk.php line 10:

  Class 'Laravel\Dusk\Console\DuskCommand' not found  

Я попытался переместить пакет Dusk в require, чтобы он был доступен в рабочей среде (я знаю, что это не идеально), но в основном поставщике услуг Dusk есть строка, которая создает исключение при запуске в рабочей среде, предотвращая это:

# From: vendor/laravel/dusk/src/DuskServiceProvider.php
if ($this->app->environment('production')) {
    throw new Exception('It is unsafe to run Dusk in production.');
}

Я пытаюсь придумать самое элегантное решение, позволяющее сделать мою пользовательскую команду Dusk частью приложения и доступной локально, не вызывая ошибок в рабочей среде.

Одна идея: написать мою команду Dusk как отдельный пакет, это тоже только в require-dev.

Любые другие идеи?


person sbuck    schedule 25.01.2019    source источник


Ответы (2)


Я только что взглянул на API, вы можете сделать это:

Вы можете переместить свою команду в App\Console\Commmands\Local\DuskCommand.php.

По умолчанию, если вы проверите метод commands() в ядре, он будет загружать только команды, найденные в App\Console\Commands. Это не будет включать подкаталоги.

/**
 * Register the commands for the application.
 *
 * @return void
 */
protected function commands()
{
    $this->load(__DIR__.'/Commands');

    require base_path('routes/console.php');
}

Это метод commands() по умолчанию. Вы можете переключить эту реализацию на приведенную ниже:

/**
 * Register the commands for the application.
 *
 * @return void
 */
protected function commands()
{
    $paths = [
        __DIR__ . '/Commands'
    ]; 

    if(app()->environment('local')) {
        $paths[] = __DIR__ . '/Commands/Local';
    }

    $this->load($paths);

    require base_path('routes/console.php');
}

Итак, локально мы также собираемся загружать команды, основанные на App\Console\Commands\Local.

Правда, я сам не пробовал, но предполагаю, что должно сработать.

Изменить: я попробовал, и, похоже, он работает нормально. Я подумал, я попытаюсь объяснить это немного больше. По сути, после выполнения composer dump-autoload Laravel прослушивает это событие и делает две вещи:

"post-autoload-dump": [
    "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
    "@php artisan package:discover --ansi"
]

Второй пытается запустить команду Auto-Package Discovery, и здесь у него ничего не получится. Исполняемый файл Artisan фактически загружает приложение с ядром консоли.

$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);

$status = $kernel->handle(
    $input = new Symfony\Component\Console\Input\ArgvInput,
    new Symfony\Component\Console\Output\ConsoleOutput
);

При разрешении ядра оно также попытается загрузить нужные ему команды, чтобы они были доступны для Artisan, и здесь он терпит неудачу.

Однако, как я упоминал выше, если вы загружаете только те команды, которые вам нужны в рабочей среде, этой проблемы не возникнет.

person Mozammil    schedule 25.01.2019
comment
Наткнулся на еще один блокпост: поскольку MyDusk.php расширяет Laravel\Dusk\Console\DuskCommand;, композитор выдает ошибку при производстве, когда не может найти DuskCommand. Чтобы обойти это, я мог бы переместить MyDusk из каталога app/, чтобы он не загружался автоматически psr-4 в рабочей среде (и добавить его новое местоположение в autoload-dev). Но теперь это 2 нетипичных шага, чтобы заставить это работать - я думаю, что на данный момент имеет смысл просто сделать его собственным пакетом - esp, потому что я вижу, что он полезен в других проектах. - person sbuck; 01.02.2019
comment
На самом деле я нахожу прямо противоположное поведение в Laravel 7+. Команды в подкаталогах автоматически загружаются с помощью метода load() ядра консоли. К сожалению, я не нашел простого способа выборочно игнорировать один или несколько из автозагрузки. - person Nick Poulos; 20.05.2020

Принятый ответ, кажется, не работает в Laravel 6. Это сработало для меня:

  1. Создайте свою команду с помощью php artisan make:command YourCommand и переместите ее в app/Console/Local.
  2. Измените его пространство имен на App\Console\Local.
  3. Затем в app/Console/Kernel.php:
protected function commands()
{
    $paths = [
        __DIR__ . '/Commands'
    ];

    if(app()->environment('local')) {
        $paths[] = __DIR__ . '/Local';
    }

    $this->load($paths);

    require base_path('routes/console.php');
}
  1. Наслаждаться ;)
person juanmanavarro    schedule 27.05.2020