dschuppelius / php-error-toolkit
Reused codes for my api php sdks
Installs: 930
Dependents: 1
Suggesters: 0
Security: 0
Stars: 1
Watchers: 2
Forks: 0
Open Issues: 0
pkg:composer/dschuppelius/php-error-toolkit
Requires
- php: >=8.1 <8.5
- psr/log: ^3.0
Requires (Dev)
- phpunit/phpunit: ^11.3@dev
This package is auto-updated.
Last update: 2026-01-26 15:36:19 UTC
README
A PSR-3 compliant logging library built for PHP 8.1+ 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 - β±οΈ Timer Logging - Measure execution time with
logInfoWithTimer()and similar methods - π Conditional Logging -
logInfoIf(),logErrorUnless()for conditional log output - π§ OS Helper - Cross-platform system detection and utilities
- π¨ Cross-Platform - Windows, Linux and macOS terminal support
- π§ͺ Fully Tested - Comprehensive test suite with PHPUnit
Installation
Install via Composer:
composer require dschuppelius/php-error-toolkit
Requirements
- PHP 8.1 to 8.4
- 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 unusableALERT(1) - Action must be taken immediatelyCRITICAL(2) - Critical conditionsERROR(3) - Error conditionsWARNING(4) - Warning conditionsNOTICE(5) - Normal but significant conditionINFO(6) - Informational messagesDEBUG(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']); } }
Conditional Logging
Log messages only when conditions are met:
use ERRORToolkit\Traits\ErrorLog; class DataProcessor { use ErrorLog; public function process(array $data, bool $verbose = false) { // Log only if condition is true $this->logDebugIf($verbose, 'Verbose mode enabled'); // Log only if condition is false $this->logWarningUnless(count($data) > 0, 'Empty data received'); // Works with all log levels $this->logInfoIf($verbose, 'Processing started', ['count' => count($data)]); $this->logErrorUnless($this->validate($data), 'Validation failed'); } }
Log with Timer
Measure execution time of operations:
use ERRORToolkit\Traits\ErrorLog; class PerformanceService { use ErrorLog; public function heavyOperation() { // Execute callback and log duration $result = $this->logInfoWithTimer(function() { // Heavy processing... return $this->processData(); }, 'Heavy operation'); // Logs: "Heavy operation (completed in 123.45 ms)" return $result; } public function apiCall() { // Works with all log levels return $this->logDebugWithTimer(function() { return file_get_contents('https://api.example.com/data'); }, 'API request'); } }
Log and Return
Log a message and return a value in one call:
use ERRORToolkit\Traits\ErrorLog; class Calculator { use ErrorLog; public function calculate(int $value): int { $result = $value * 2; // Log and return in one call return $this->logDebugAndReturn($result, 'Calculation complete', ['input' => $value]); } public function findUser(int $id): ?User { $user = $this->repository->find($id); return $user !== null ? $this->logInfoAndReturn($user, 'User found', ['id' => $id]) : $this->logWarningAndReturn(null, 'User not found', ['id' => $id]); } }
Log Exceptions
Log exceptions with full stack trace:
use ERRORToolkit\Traits\ErrorLog; use Psr\Log\LogLevel; class ExceptionHandler { use ErrorLog; public function handle(\Throwable $e): void { // Log exception with full context (file, line, trace) self::logException($e); // With custom log level self::logException($e, LogLevel::CRITICAL); // With additional context self::logException($e, LogLevel::ERROR, ['user_id' => 123]); } }
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 |
|---|---|
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:
- Primary: Uses configured PSR-3 logger
- Fallback 1: PHP error_log() if configured
- Fallback 2: System syslog with project-specific facility
- 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
Helper Classes
OsHelper
Cross-platform operating system detection and utilities:
use ERRORToolkit\Helper\OsHelper; // OS Detection OsHelper::isWindows(); // true on Windows OsHelper::isLinux(); // true on Linux OsHelper::isMacOS(); // true on macOS OsHelper::isUnix(); // true on Linux or macOS OsHelper::getOsName(); // 'Windows', 'Linux', 'macOS' // Path Utilities OsHelper::getPathSeparator(); // '\' on Windows, '/' on Unix OsHelper::getEnvPathSeparator(); // ';' on Windows, ':' on Unix OsHelper::getHomeDirectory(); // User's home directory OsHelper::getTempDirectory(); // System temp directory // Executable Utilities OsHelper::isExecutable('/path/to/file'); // Check if file is executable OsHelper::findExecutable('git'); // Find executable in PATH // User Information OsHelper::getCurrentUsername(); // Current user name OsHelper::getCurrentUserId(); // UID (Unix only) OsHelper::isPrivilegedUser(); // Check for root/admin // System Information OsHelper::getCpuCoreCount(); // Number of CPU cores OsHelper::getArchitecture(); // System architecture (x86_64, arm64, etc.) OsHelper::getKernelVersion(); // Kernel version OsHelper::getSystemInfo(); // Complete system info array // Environment Variables OsHelper::getEnv('HOME', '/default'); // Get env var with default OsHelper::setEnv('MY_VAR', 'value'); // Set env var
TerminalHelper
Terminal detection and capabilities:
use ERRORToolkit\Helper\TerminalHelper; TerminalHelper::isTerminal(); // Check if running in terminal TerminalHelper::isDebugConsole(); // Check if running in debug console TerminalHelper::getCursorColumn(); // Get current cursor position
PhpUnitHelper
PHPUnit-specific utilities:
use ERRORToolkit\Helper\PhpUnitHelper; PhpUnitHelper::isRunningInPhpunit(); // Check if running in PHPUnit PhpUnitHelper::supportsColors(); // Check 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
ErrorLogtrait - Helper Classes - Reusable utilities for OS detection, terminal handling, PHPUnit support
- PSR-3 Compliant - Standard logging interface
License
MIT License. See LICENSE file for details.
Author
Daniel JΓΆrg Schuppelius
- Website: schuppelius.org
- Email: info@schuppelius.org
Contributing
This is a personal toolkit for Daniel Schuppelius's projects. For bugs or feature requests, please open an issue.