Этот сниппет даёт минималистичный, но практичный логгер для CLI/cron-скриптов на PHP: читабельные статусы, цвет (если терминал поддерживает), отдельный поток для ошибок и выравнивание Key: Value.
Что решаем
- Читабельные статусы:
[i],[OK],[WARN],[ERR]. - Ошибки в
STDERR(удобно для логов и мониторинга). - Цветной вывод через ANSI только когда это реальный терминал (TTY).
- Принудительное отключение цветов через переменную окружения
NO_COLOR. - Защита от терминальных инъекций: очищаем пользовательский текст от ANSI/CSI и управляющих символов.
Когда не подходит: если нужна полноценная CLI-обвязка с командами/аргументами/help/progress/tables — лучше, например, Symfony Console.
Установка
Через Composer (рекомендуется):
composer require da41b94c/php-console-logger
Ручная установка: скопируй src/Console.php в проект и подключи вручную.
Готовое решение
final class Console
{
private const Esc = "\x1B[";
private const Reset = "\x1B[0m";
private const CInfo = "36;1";
private const CSuccess = "32;1";
private const CWarn = "33;1";
private const CError = "31;1";
private const CMuted = "90";
public static function Write(string $Text): void
{
fwrite(STDOUT, $Text);
}
public static function WriteLn(string $Text = ''): void
{
fwrite(STDOUT, $Text . PHP_EOL);
}
public static function Err(string $Text): void
{
fwrite(STDERR, $Text);
}
public static function ErrLn(string $Text): void
{
fwrite(STDERR, $Text . PHP_EOL);
}
public static function Info(string $Text): void
{
$Text = self::CleanText($Text);
self::WriteLn(self::Paint("[i] " . $Text, self::CInfo));
}
public static function Success(string $Text): void
{
$Text = self::CleanText($Text);
self::WriteLn(self::Paint("[OK] " . $Text, self::CSuccess));
}
public static function Warn(string $Text): void
{
$Text = self::CleanText($Text);
self::WriteLn(self::Paint("[WARN] " . $Text, self::CWarn));
}
public static function Error(string $Text): void
{
$Text = self::CleanText($Text);
self::ErrLn(self::Paint("[ERR] " . $Text, self::CError));
}
public static function Debug(string $Text): void
{
$Text = self::CleanText($Text);
self::WriteLn(self::Paint("[DBG] " . $Text, self::CMuted));
}
public static function Kv(string $Key, string $Value, int $KeyWidth = 22): void
{
$Key = self::CleanText($Key);
$Value = self::CleanText($Value);
$Key = self::PadRight($Key, $KeyWidth);
self::WriteLn($Key . ": " . $Value);
}
public static function PadRight(string $Text, int $Width): string
{
if ($Width <= 0) {
return $Text;
}
if (function_exists('mb_strwidth')) {
$Len = (int)mb_strwidth($Text, 'UTF-8');
$Pad = $Width - $Len;
if ($Pad > 0) {
return $Text . str_repeat(' ', $Pad);
}
return $Text;
}
return str_pad($Text, $Width, ' ', STR_PAD_RIGHT);
}
public static function Paint(string $Text, string $AnsiCode): string
{
if (!self::SupportsAnsi()) {
return $Text;
}
return self::Esc . $AnsiCode . "m" . $Text . self::Reset;
}
public static function SupportsAnsi(): bool
{
if (getenv('NO_COLOR') !== false) {
return false;
}
if (!self::IsTty(STDOUT)) {
return false;
}
$Term = (string)getenv('TERM');
if ($Term === '' || $Term === 'dumb') {
return false;
}
return true;
}
public static function IsTty($Stream): bool
{
if (function_exists('stream_isatty')) {
return @stream_isatty($Stream);
}
if (function_exists('posix_isatty')) {
return @posix_isatty($Stream);
}
return false;
}
/**
* Чистим только пользовательский текст:
* - убираем ANSI/CSI-последовательности
* - убираем управляющие символы (кроме \n и \t)
*/
public static function CleanText(string $Text): string
{
$Text = (string)preg_replace('/\x1B\[[0-?]*[ -\/]*[@-~]/', '', $Text);
$Text = (string)preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/', '', $Text);
return $Text;
}
}
Пример использования
В проекте с Composer:
require_once __DIR__ . '/vendor/autoload.php';
Console::Info("Started");
Console::Kv("id", "777");
Console::Success("OK");
Console::Warn("id is empty");
Console::Error("API failed: 429 Too Many Requests");
Если подключаешь вручную:
require_once __DIR__ . '/src/Console.php';
Console::Info("Started");
Console::Kv("id", "777");
Console::Success("OK");
Console::Warn("id is empty");
Console::Error("API failed: 429 Too Many Requests");
Совместимость
- PHP: 7.3+
- Linux/macOS/Windows (ANSI-цвета зависят от терминала)
- Отключение цвета:
NO_COLOR=1
Тест/проверка
php -r 'require "src/Console.php"; Console::Info("Test"); Console::Success("OK"); Console::Warn("Warn"); Console::Error("Err");'
NO_COLOR=1 php -r 'require "src/Console.php"; Console::Info("No color");'
Альтернативы
- Symfony Console — если нужен полноценный CLI-фреймворк (команды, аргументы, help, прогресс, таблицы).
- Monolog — если нужны структурированные логи в файл/систему логирования.
Комментарии
0Нашли ошибку или хотите дополнить материал?