将控制台输出记录器添加到从artisan命令类调用的服务类的最佳做法是什么。
示例代码:
<?php
class Import extends Command
{
public function handle()
{
/** @var \Services\ServiceImport $service */
$service = resolve($this->resolvers[$db])
->setCommand($this);
# Console output
$this->info(sprintf('Starting import for "%s"', $service::SERVICE_NAME));
$imported = $service->import($this->argument('file'));
$this->info(sprintf('Total rows imported: %d', $imported));
}
}
}
/** Different file, service from container */
class ServiceImport extends Service
{
protected $cmd;
public function import($file)
{
# Need this console output
$this->cmd->info(sprintf('Importing file "%s"', $file));
// [...] More stuff goes on..this illustrates my point
}
public function setCommand(Command $cmd)
{
$this->cmd = $cmd;
return $this;
}
}
这很有效,但在尝试单元测试ServiceImport
时失败了,因为$cmd
没有设置......而且我还没有找到一种方法来模拟Command
1}}让这个工作。我该如何做到这一点?
我确定我错过了什么。我是如何使用服务的?我不能成为唯一一个在处理期间运行持续运行详细日志的人。
使用Laravel 5.4,artisan命令。
我不想使用Log::
,因为我专门写入控制台(具有漂亮的Symfony颜色)。
答案 0 :(得分:1)
由于您只想创建日志输出,您可以通过检查null
来解决此问题。
在您的服务中,只需使用函数参数注入命令依赖项,如下所示:
public function import($file, Command $cmd = null)
{
# Need this console output
if($cmd != null) {
$this->cmd->info(sprintf('Importing file "%s"', $file));
}
// [...] More stuff goes on..this illustrates my point
}
在测试中,您可以轻松省略$cmd
参数,因为这不会影响您的服务代码。
如果您过度使用此类输出,请使用以下函数创建Trait或基类:
public function info(string $message, Command $cmd = null)
{
if($cmd != null){
$cmd->info($message);
} else {
//perhaps log message otherwise in test environment
// or when service is used outside of artisan commands
}
}
您可以在服务中随处使用
$this->info(sprintf('Importing file "%s"', $file), $cmd);