Php 忽略生产上的自定义Laravel Artisan命令
我已经编写了一个自定义Artisan命令(我们称之为Php 忽略生产上的自定义Laravel Artisan命令,php,laravel,laravel-artisan,laravel-dusk,Php,Laravel,Laravel Artisan,Laravel Dusk,我已经编写了一个自定义Artisan命令(我们称之为mydash.php),它扩展/抽象了核心dash命令的一些功能 此自定义命令从黄昏包中扩展Laravel\dash\Console\dashCommand 问题是,在生产中没有安装Dusk软件包(它位于composer.json中的require dev下) 因此,当composer在生产环境中生成自动加载文件时,当它到达mydash.php时会出错,因为它找不到Laravel\dash\Console\dashcommand PHP Fat
mydash.php
),它扩展/抽象了核心dash命令的一些功能
此自定义命令从黄昏包中扩展Laravel\dash\Console\dashCommand
问题是,在生产中没有安装Dusk软件包(它位于composer.json
中的require dev
下)
因此,当composer在生产环境中生成自动加载文件时,当它到达mydash.php
时会出错,因为它找不到Laravel\dash\Console\dashcommand
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
我尝试将Dash软件包移动到require
,这样它就可以在生产环境中使用(我知道这并不理想),但核心Dash服务提供商中有一行在生产环境中运行时抛出异常,从而阻止了这一点:
# From: vendor/laravel/dusk/src/DuskServiceProvider.php
if ($this->app->environment('production')) {
throw new Exception('It is unsafe to run Dusk in production.');
}
我正试图想出一个最优雅的解决方案,让我的自定义黄昏命令成为应用程序的一部分,并且可以在本地访问,而不会在生产中引发错误。
一个想法是:将我的Dusk命令作为自己的包编写,这也仅在require-dev中
还有其他想法吗?我刚看了一下API,您可以这样做: 您可以将命令移动到
App\Console\Commmands\Local\dashcommand.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');
}
因此,在local中,我们还将加载基于App\Console\commands\local
的命令
诚然,我自己没有尝试过,但我认为它应该会起作用
编辑:我试了一下,它似乎工作得很好。我想,我应该试着多解释一下。基本上,在完成编写器转储自动加载后,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中:
受保护的函数命令()
{
$path=[
__目录。'/Commands'
];
if(app()->environment('local')){
$paths[]=\uuuuu DIR\uuuu.'./Local';
}
$this->load($path);
需要基本路径('routes/console.php');
}
享受;)李>
遇到了另一个障碍:因为mydash.php
正在扩展Laravel\dash\Console\dashcommand
,composer在产品中找不到命令时抛出错误。为了解决这个问题,我可以将mydash
移出app/
目录,这样它就不会在生产中自动加载psr-4(并将它的新位置添加到autoloaddev
)。但是,现在这是两个非典型的步骤来让它工作-我认为在这一点上,它是有意义的,只是让它自己的包-esp,因为我可以看到它在其他项目中是有用的。我实际上发现完全相反的行为在Laravel 7+。子目录中的命令绝对是通过控制台内核的load()方法自动加载的。不幸的是,我发现没有简单的方法可以选择性地忽略自动加载中的一个或多个。