Install via Composer:
composer require code-lts/cli-tools
Ensure your project uses PHP 8.1+, PHPUnit 12, and Symfony Console v8 (or later).
Basic Error Formatting:
use CodeLts\CliTools\Error;
use CodeLts\CliTools\AnalysisResult;
use CodeLts\CliTools\OutputFormat;
$errors = [new Error("Test error", __FILE__, 10)];
$result = new AnalysisResult($errors, [], [], []);
OutputFormat::displayUserChoiceFormat(
OutputFormat::OUTPUT_FORMAT_TABLE,
$result,
base_path(),
new \Symfony\Component\Console\Output\ConsoleOutput()
);
Key Classes to Know:
Error: Represents file-specific errors with messages, paths, and line numbers.AnalysisResult: Aggregates errors, warnings, and internal issues.OutputFormat: Handles output formatting (JUnit, GitLab, TeamCity, etc.).SymfonyOutput: Laravel-friendly output wrapper (extend \Symfony\Component\Console\Output\OutputInterface).First Use Case: Format PHPStan/PHPUnit errors for CI/CD pipelines (e.g., GitLab, GitHub Actions) or local development with colored tables.
class StaticAnalysisService {
public function analyze(string $file): AnalysisResult {
$errors = $this->detectIssues($file);
return new AnalysisResult($errors, [], [], []);
}
public function outputResults(AnalysisResult $result): void {
OutputFormat::displayUserChoiceFormat(
OutputFormat::OUTPUT_FORMAT_GITHUB,
$result,
base_path(),
app('console.output')
);
}
}
app('console.output') for seamless CLI output.OutputFormat::displayUserChoiceFormat(
OutputFormat::OUTPUT_FORMAT_GITLAB,
$result,
base_path()
);
OutputFormat::displayUserChoiceFormat(
OutputFormat::OUTPUT_FORMAT_GITHUB,
$result,
base_path()
);
OutputFormat::displayUserChoiceFormat(
OutputFormat::OUTPUT_FORMAT_TEAMCITY,
$result,
base_path()
);
$format = $this->getUserInput('Select format: [table/gitlab/github]');
OutputFormat::checkOutputFormatIsValid($format);
if (\CodeLts\CliTools\Utils::isCiDetected()) {
$format = OutputFormat::OUTPUT_FORMAT_GITLAB;
} else {
$format = OutputFormat::OUTPUT_FORMAT_TABLE;
}
\CodeLts\CliTools\File\FileWriter::write('report.xml', $xmlContent);
$content = \CodeLts\CliTools\File\FileReader::read('report.xml');
use Illuminate\Support\Facades\Storage;
Storage::put('report.xml', $xmlContent);
$content = Storage::get('report.xml');
$this->output->writeFormatted(\CodeLts\CliTools\File\AnsiEscapeSequences::ERASE_TO_LINE_END);
$this->output->writeln('<comment>Processing...</comment>');
$this->output->writeFormatted(AnsiEscapeSequences::ERASE_TO_LINE_END);
$this->output->writeln('<info>Done!</info>');
\Illuminate\Console\Command and inject SymfonyOutput:
use CodeLts\CliTools\Symfony\SymfonyOutput;
class AnalyzeCommand extends Command {
protected $output;
public function __construct() {
parent::__construct();
$this->output = new SymfonyOutput($this->getOutput());
}
protected function execute(InputInterface $input, OutputInterface $output): int {
$result = $this->analyze();
OutputFormat::displayUserChoiceFormat(
OutputFormat::OUTPUT_FORMAT_TABLE,
$result,
base_path(),
$this->output
);
return Command::SUCCESS;
}
}
OutputFormat:
$this->app->bind(\CodeLts\CliTools\OutputFormat::class, function () {
return new \CodeLts\CliTools\OutputFormat();
});
SymfonyOutput in tests:
$mockOutput = $this->createMock(\Symfony\Component\Console\Output\OutputInterface::class);
$output = new \CodeLts\CliTools\Symfony\SymfonyOutput($mockOutput);
jobs.failed):
public function handle(JobFailed $event) {
$errors = [$event->exception->getMessage()];
$result = new AnalysisResult($errors, [], [], []);
OutputFormat::displayUserChoiceFormat(
OutputFormat::OUTPUT_FORMAT_TABLE,
$result,
base_path(),
app('console.output')
);
}
Class 'CodeLts\CliTools\Error' not found or PHP Fatal Error: Required parameter $message follows optional.composer.json:
"require": {
"php": "^8.1"
}
Class 'Symfony\Component\Console\Output\ConsoleOutput' not found.composer require symfony/console:^8.0
symfony/console:^5|^6 (but this violates the package’s requirements).PHPUnit\Framework\TestSuite not found.composer require phpunit/phpunit:^12.0
Error class’s line property is nullable (PHP 8.1+ feature). Older code may throw:
$error = new Error("Message", __FILE__, null); // Valid in v1.5.0+
int|null.Utils::isCiDetected() may return false in local Docker environments or custom CI setups.if (\CodeLts\CliTools\Utils::isCiDetected() || getenv('CI') === 'true') {
// CI logic
}
isDecorated() before using ANSI sequences:
if ($this->output->isDecorated()) {
$this->output->writeFormatted(AnsiEscapeSequences::ERASE_TO_LINE_END);
}
try {
OutputFormat::checkOutputFormatIsValid('invalid-format');
} catch (\CodeLts\CliTools\Exceptions\FormatNotFoundException $e) {
$this->error($e->getMessage());
}
OUTPUT_FORMAT_TABLE, OUTPUT_FORMAT_GITHUB, OUTPUT_FORMAT_GITLAB, etc. (see OutputFormat::VALID_OUTPUT_FORMATS).AnalysisResult
How can I help you explore Laravel packages today?