Reputation: 1094
What is the best practice to add a console output logger to service classes called from artisan command classes.
Example Code:
<?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;
}
}
This works, but fails when attempting to unit test ServiceImport
, because $cmd
isn't set... And I hadn't figured out a way to Mock a Command
get this working, either. How do I accomplish this?
I'm certain I'm missing something. Is it how I'm using Services? I can't be the only person looking to run a constant running verbose log during processing.
Using Laravel 5.4, artisan command.
I don't want to use Log::
as I specifically write to the console (with nice Symfony colors).
Upvotes: 1
Views: 2410
Reputation: 240
As you only want to create log-output you could solve this with checks for null
.
In your service just inject the command dependency with the function parameters like so:
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
}
In your tests you can easily omit the $cmd
argument as this should not influence your Services code.
If you excessively use this kind of output, create a Trait or a base class with functions like:
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
}
}
And you can use this everywhere in your Service
$this->info(sprintf('Importing file "%s"', $file), $cmd);
Upvotes: 1