忽略生产中的自定义 Laravel Artisan 命令
Ignore a custom Laravel Artisan command on production
我编写了一个自定义的 Artisan 命令(我们称之为 MyDusk.php
),expands/abstracts 核心 Dusk 命令的一些功能。
此自定义命令从 Dusk 包中扩展 Laravel\Dusk\Console\DuskCommand
。
问题是,在生产环境中没有安装 Dusk 包(它在 composer.json
中的 require-dev
下)
因此,当 composer 在生产环境中生成其自动加载文件时,它会在到达 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 中。
还有其他想法吗?
我刚刚看了一下 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"
]
第二个正在尝试 运行 自动打包发现命令,这就是它会失败的地方。 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 可以使用它们,这就是它失败的地方。
然而,就像我上面提到的,如果你只启动你在生产中需要的命令,这个问题就不会发生。
已接受的答案似乎不适用于 Laravel 6。这对我有用:
- 使用
php artisan make:command YourCommand
创建您的命令并将其移动到 app/Console/Local。
- 将其命名空间更改为 App\Console\Local。
- 然后,在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');
}
- 尽情享受 ;)
我编写了一个自定义的 Artisan 命令(我们称之为 MyDusk.php
),expands/abstracts 核心 Dusk 命令的一些功能。
此自定义命令从 Dusk 包中扩展 Laravel\Dusk\Console\DuskCommand
。
问题是,在生产环境中没有安装 Dusk 包(它在 composer.json
中的 require-dev
下)
因此,当 composer 在生产环境中生成其自动加载文件时,它会在到达 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 中。
还有其他想法吗?
我刚刚看了一下 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"
]
第二个正在尝试 运行 自动打包发现命令,这就是它会失败的地方。 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 可以使用它们,这就是它失败的地方。
然而,就像我上面提到的,如果你只启动你在生产中需要的命令,这个问题就不会发生。
已接受的答案似乎不适用于 Laravel 6。这对我有用:
- 使用
php artisan make:command YourCommand
创建您的命令并将其移动到 app/Console/Local。 - 将其命名空间更改为 App\Console\Local。
- 然后,在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');
}
- 尽情享受 ;)