dschuppelius/php-error-toolkit

Reused codes for my api php sdks

Installs: 713

Dependents: 1

Suggesters: 0

Security: 0

Stars: 1

Watchers: 2

Forks: 0

Open Issues: 0

pkg:composer/dschuppelius/php-error-toolkit

v2.0.3 2026-01-10 22:05 UTC

README

PHP Version PSR-3 Compliant License: MIT

A PSR-3 compliant logging library built for PHP 8.2+ with a focus on console and file logging. Designed as a lightweight, reusable component for modern PHP applications.

Features

  • 🎯 PSR-3 Compliant - Full compatibility with PSR-3 logging standards
  • πŸ–₯️ Console Logging - Colored output with ANSI support and terminal detection
  • πŸ“„ File Logging - Automatic log rotation and fail-safe mechanisms
  • 🏭 Factory Pattern - Clean instantiation with singleton behavior
  • 🌐 Global Registry - Centralized logger management across your application
  • ✨ Magic Methods - Convenient logDebug(), logInfo(), logErrorAndThrow() methods via trait
  • 🎨 Cross-Platform - Windows and Unix/Linux terminal support
  • πŸ§ͺ Fully Tested - Comprehensive test suite with PHPUnit

Installation

Install via Composer:

composer require dschuppelius/php-error-toolkit

Requirements

  • PHP 8.1 or higher
  • PSR-3 Log Interface

Quick Start

Basic Usage with Console Logger

use ERRORToolkit\Factories\ConsoleLoggerFactory;

// Create a console logger
$logger = ConsoleLoggerFactory::getLogger();

// Log messages with different levels
$logger->info('Application started');
$logger->warning('This is a warning message');
$logger->error('An error occurred');

File Logging

use ERRORToolkit\Factories\FileLoggerFactory;

// Create a file logger
$logger = FileLoggerFactory::getLogger('/path/to/logfile.log');

// Log with context
$logger->error('Database connection failed', [
    'host' => 'localhost',
    'port' => 3306,
    'error' => 'Connection timeout'
]);

Using the ErrorLog Trait

Add logging capabilities to any class:

use ERRORToolkit\Traits\ErrorLog;
use ERRORToolkit\Factories\ConsoleLoggerFactory;

class MyService {
    use ErrorLog;
    
    public function __construct() {
        // Set up logging
        self::setLogger(ConsoleLoggerFactory::getLogger());
    }
    
    public function doSomething() {
        $this->logInfo('Starting operation');
        
        try {
            // Your code here
            $this->logDebug('Operation completed successfully');
        } catch (Exception $e) {
            $this->logError('Operation failed: ' . $e->getMessage());
        }
    }
}

Logger Types

Console Logger

  • Colored output with level-specific colors
  • Automatic terminal detection
  • Debug console support (VS Code, etc.)
  • Clean formatting with newline management

File Logger

  • Automatic log rotation when size limit exceeded
  • Fail-safe fallback to console/syslog
  • Customizable file size limits
  • Thread-safe file operations

Null Logger

  • Silent logger for testing/production environments
  • PSR-3 compliant no-op implementation

Global Logger Registry

Manage loggers globally across your application:

use ERRORToolkit\LoggerRegistry;
use ERRORToolkit\Factories\FileLoggerFactory;

// Set a global logger
LoggerRegistry::setLogger(FileLoggerFactory::getLogger('app.log'));

// Use it anywhere in your application
if (LoggerRegistry::hasLogger()) {
    $logger = LoggerRegistry::getLogger();
    $logger->info('Using global logger');
}

// Reset when needed
LoggerRegistry::resetLogger();

Log Levels

Supports all PSR-3 log levels with integer-based filtering:

  • EMERGENCY (0) - System is unusable
  • ALERT (1) - Action must be taken immediately
  • CRITICAL (2) - Critical conditions
  • ERROR (3) - Error conditions
  • WARNING (4) - Warning conditions
  • NOTICE (5) - Normal but significant condition
  • INFO (6) - Informational messages
  • DEBUG (7) - Debug-level messages

ErrorLog Trait Features

The ErrorLog trait provides comprehensive logging capabilities with multiple advanced features:

Magic Methods

All PSR-3 log levels are available as magic methods:

use ERRORToolkit\Traits\ErrorLog;

class MyClass {
    use ErrorLog;

    public function example() {
        // Instance methods - these methods are automatically available
        $this->logDebug('Debug message');
        $this->logInfo('Info message');
        $this->logNotice('Notice message');
        $this->logWarning('Warning message');
        $this->logError('Error message');
        $this->logCritical('Critical message');
        $this->logAlert('Alert message');
        $this->logEmergency('Emergency message');
        
        // All methods support context arrays
        $this->logError('Database error', ['table' => 'users', 'id' => 123]);
    }

    public static function staticExample() {
        // Static methods - all static magic methods are available
        self::logDebug('Static debug message');
        self::logInfo('Static info message');
        self::logNotice('Static notice message');
        self::logWarning('Static warning message');
        self::logError('Static error message');
        self::logCritical('Static critical message');
        self::logAlert('Static alert message');
        self::logEmergency('Static emergency message');
        
        // Static methods also support context
        self::logInfo('User action', ['user' => 'admin', 'action' => 'login']);
    }
}

Log and Throw Exceptions

Combine logging and exception throwing in a single call with log{Level}AndThrow():

use ERRORToolkit\Traits\ErrorLog;
use RuntimeException;
use InvalidArgumentException;

class ValidationService {
    use ErrorLog;

    public function validateUser(array $data): void {
        if (empty($data['email'])) {
            // Logs error and throws exception in one call
            $this->logErrorAndThrow(
                InvalidArgumentException::class,
                'Email is required'
            );
        }
        
        if (!filter_var($data['email'], FILTER_VALIDATE_EMAIL)) {
            // With context array
            $this->logWarningAndThrow(
                InvalidArgumentException::class,
                'Invalid email format',
                ['email' => $data['email']]
            );
        }
    }

    public function processPayment(float $amount): void {
        try {
            // Payment processing...
        } catch (\Exception $e) {
            // With exception chaining
            $this->logCriticalAndThrow(
                RuntimeException::class,
                'Payment processing failed',
                ['amount' => $amount],
                $e  // Previous exception for chaining
            );
        }
    }

    public static function validateConfig(array $config): void {
        if (!isset($config['api_key'])) {
            // Static usage
            self::logErrorAndThrow(
                RuntimeException::class,
                'API key not configured'
            );
        }
    }
}

Available log-and-throw methods:

Method Log Level
logDebugAndThrow() DEBUG
logInfoAndThrow() INFO
logNoticeAndThrow() NOTICE
logWarningAndThrow() WARNING
logErrorAndThrow() ERROR
logCriticalAndThrow() CRITICAL
logAlertAndThrow() ALERT
logEmergencyAndThrow() EMERGENCY

Method signature:

log{Level}AndThrow(
    string $exceptionClass,    // Exception class to throw (e.g., RuntimeException::class)
    string $message,           // Error message (used for both log and exception)
    array $context = [],       // Optional: Context array for logging
    ?Throwable $previous = null // Optional: Previous exception for chaining
): never

Logger Management

The trait provides flexible logger management:

use ERRORToolkit\Traits\ErrorLog;
use ERRORToolkit\Factories\FileLoggerFactory;

class MyService {
    use ErrorLog;
    
    public function __construct() {
        // Set a specific logger for this class
        self::setLogger(FileLoggerFactory::getLogger('service.log'));
        
        // Or use global logger from registry (automatic fallback)
        self::setLogger(); // Uses LoggerRegistry::getLogger()
    }
}

Automatic Project Detection

The trait automatically detects project names from class namespaces:

namespace MyCompany\ProjectName\Services;

use ERRORToolkit\Traits\ErrorLog;

class UserService {
    use ErrorLog;
    
    public function process() {
        // Project name "MyCompany" is automatically detected
        // Log entry: [2025-12-29 10:30:00] info [MyCompany::UserService::process()]: Processing user
        $this->logInfo('Processing user');
    }
}

Fallback Logging System

When no logger is available, the trait provides intelligent fallbacks:

  1. Primary: Uses configured PSR-3 logger
  2. Fallback 1: PHP error_log() if configured
  3. Fallback 2: System syslog with project-specific facility
  4. Fallback 3: File logging to system temp directory
class EmergencyService {
    use ErrorLog;
    
    public function criticalOperation() {
        // Even without explicit logger setup, this will work
        // Falls back through: error_log β†’ syslog β†’ temp file
        self::logEmergency('System failure detected');
    }
}

Context Support

All logging methods support PSR-3 context arrays:

class ApiService {
    use ErrorLog;
    
    public function handleRequest($request) {
        $context = [
            'method' => $request->method,
            'url' => $request->url,
            'user_id' => $request->user?->id,
            'timestamp' => time()
        ];
        
        $this->logInfo('API request received', $context);
        
        try {
            // Process request
        } catch (Exception $e) {
            $this->logError('API request failed', [
                ...$context,
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
        }
    }
}

Configuration

Log Level Filtering

use ERRORToolkit\Logger\ConsoleLogger;
use Psr\Log\LogLevel;

// Only log warnings and above
$logger = new ConsoleLogger(LogLevel::WARNING);
$logger->info('This will be ignored');
$logger->warning('This will be logged');

File Logger Options

use ERRORToolkit\Logger\FileLogger;

$logger = new FileLogger(
    logFile: '/var/log/app.log',
    logLevel: LogLevel::INFO,
    failSafe: true,           // Fallback to console/syslog on file errors
    maxFileSize: 5000000,     // 5MB before rotation
    rotateLogs: true          // Create .old backup when rotating
);

Testing

Run the test suite:

composer test

Or run PHPUnit directly:

vendor/bin/phpunit

Cross-Platform Terminal Support

The toolkit automatically detects:

  • Windows VT100 support via sapi_windows_vt100_support()
  • Unix/Linux TTY via posix_isatty()
  • Debug consoles (VS Code, PHPStorm, etc.)
  • PHPUnit color configuration

Architecture

  • Factory Pattern - All loggers created via factories with singleton behavior
  • Strategy Pattern - Different logging strategies (Console, File, Null)
  • Registry Pattern - Global logger management
  • Trait-based - Easy integration via ErrorLog trait
  • PSR-3 Compliant - Standard logging interface

License

MIT License. See LICENSE file for details.

Author

Daniel JΓΆrg Schuppelius

Contributing

This is a personal toolkit for Daniel Schuppelius's projects. For bugs or feature requests, please open an issue.