Сервер: Console для PHP вывод логов в консоль

Этот сниппет даёт минималистичный, но практичный логгер для 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 — если нужны структурированные логи в файл/систему логирования.

GitHub: https://github.com/da41b94c/php-console-logger

up: Просмотров: 219 GitHub
Материал помог? Оценка помогает находить устаревшие и спорные решения.

Комментарии

0

Нашли ошибку или хотите дополнить материал?

Комментариев пока нет.Можно первым дополнить материал или сообщить об ошибке.
Telegram