Skip to content

Repository files navigation

InitPHP Logger

A small, focused, PSR-3 compliant logger for PHP 8.0+. Ships with two built-in handlers and a tiny multiplexer that fans every log record out to several handlers at once.

Latest Stable VersionTotal DownloadsLicensePHP Version Require

At a glance

  • FileLogger — appends each record as a single line to a file, with optional date-token placeholders in the path ({year}/{month}/{day}/...).
  • PDOLogger — inserts each record as a row in a relational table, using prepared statements. Works with any PDO driver (MySQL, PostgreSQL, SQLite…).
  • Logger — accepts any number of Psr\Log\LoggerInterface instances and forwards every call to all of them, in registration order.

Everything implements Psr\Log\LoggerInterface (PSR-3 v3), so you can drop the package into any framework or library that consumes that contract — or compose it with handlers from other PSR-3 packages.

Requirements

RequirementVersion
PHP>= 8.0
psr/log^3.0
ext-pdoRequired only for PDOLogger

Installation

composer require initphp/logger

Quick start

require__DIR__ . '/vendor/autoload.php';
useInitPHP\Logger\FileLogger;
useInitPHP\Logger\Logger;
$logger = newLogger(
newFileLogger(['path' => __DIR__ . '/logs/app.log'])
);
$logger->info('Service booted in {ms}ms', ['ms' => 42]);
$logger->error('Payment {id} failed', ['id' => 9182]);

Produces, for example:

2026-05-24T14:08:22+03:00 [INFO] Service booted in 42ms
2026-05-24T14:08:22+03:00 [ERROR] Payment 9182 failed

Handlers

FileLogger

useInitPHP\Logger\FileLogger;
$logger = newFileLogger([
'path' => __DIR__ . '/logs/app-{year}-{month}-{day}.log',
]);

Path tokens ({year}, {month}, {day}, {hour}, {minute}, {second}) are resolved once, at construction time, against the process clock. The parent directory is created automatically (mode 0775) if it does not already exist. Writes use FILE_APPEND | LOCK_EX, so concurrent processes do not interleave bytes within a single record.

Full reference: docs/02-file-logger.md.

PDOLogger

useInitPHP\Logger\PDOLogger;
$pdo = newPDO('mysql:host=localhost;dbname=app;charset=utf8mb4', 'app', 'secret');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$logger = newPDOLogger(['pdo' => $pdo, 'table' => 'logs']);
$logger->error('User {user} caused an error.', ['user' => 'muhammetsafak']);
// INSERT INTO logs (level, message, date) VALUES ('ERROR', 'User muhammetsafak caused an error.', '2026-05-24 14:08:22')

Reference DDL for MySQL:

CREATETABLE `logs` (
`id`BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`level` ENUM('EMERGENCY','ALERT','CRITICAL','ERROR','WARNING','NOTICE','INFO','DEBUG') NOT NULL,
`message`TEXTNOT NULL,
`date` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `idx_logs_level_date` (`level`, `date`)
) ENGINE = InnoDB CHARSET = utf8mb4 COLLATE utf8mb4_general_ci;

PostgreSQL and SQLite variants are documented in docs/03-pdo-logger.md.

Multi-handler logging

useInitPHP\Logger\FileLogger;
useInitPHP\Logger\Logger;
useInitPHP\Logger\PDOLogger;
$logger = newLogger(
newFileLogger(['path' => __DIR__ . '/logs/app.log']),
newPDOLogger(['pdo' => $pdo, 'table' => 'logs'])
);
$logger->warning('cache miss for key {key}', ['key' => 'user:42']);
// Goes to BOTH the file and the database table.

Logger accepts any Psr\Log\LoggerInterface, including handlers from other PSR-3 packages — see docs/05-custom-handlers.md.

PSR-3 surface

Every handler exposes the full PSR-3 API:

$logger->emergency(string|\Stringable $message, array $context = []): void;
$logger->alert (string|\Stringable $message, array $context = []): void;
$logger->critical (string|\Stringable $message, array $context = []): void;
$logger->error (string|\Stringable $message, array $context = []): void;
$logger->warning (string|\Stringable $message, array $context = []): void;
$logger->notice (string|\Stringable $message, array $context = []): void;
$logger->info (string|\Stringable $message, array $context = []): void;
$logger->debug (string|\Stringable $message, array $context = []): void;
$logger->log ($level, string|\Stringable $message, array $context = []): void;

Context placeholders ({name}) are expanded with the matching key from $context. Booleans render as true / false, null renders as the empty string, \Throwable values render as Class(code): message in file:line, and anything implementing __toString() is cast to string. Arrays and non-stringable objects are skipped — see docs/06-psr3-context.md.

Unknown log levels throw Psr\Log\InvalidArgumentException, per PSR-3 §1.1.

Documentation

Topic-by-topic guides live in docs/:

Testing the package itself

composer install
composer test# PHPUnit
composer phpstan # PHPStan (level max)
composer cs-check # PHP-CS-Fixer dry-run
composer ci # all of the above

Contributing

Please read the org-wide CONTRIBUTING.md before opening a pull request. Bug reports and feature ideas go through Issues and Discussions.

Security

If you discover a security vulnerability, please follow the instructions in the org-wide SECURITY.md. Do not open a public issue.

License

Released under the MIT License. Copyright © InitPHP.

About

Small, focused PSR-3 logger for PHP 8.0+ — File & PDO handlers with a built-in multiplexer.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages