DEV Community

Cover image for PHP - Create your own logger like Monolog PSR-3 Logger Interface
F.R Michel
F.R Michel

Posted on

PHP - Create your own logger like Monolog PSR-3 Logger Interface

PHP Logger PSR-3: Logger Interface

Install the standard interfaces for Logger :

composer require psr/log
Enter fullscreen mode Exit fullscreen mode

Let's create the class that will extend the AbstractLogger

<?php

namespace DevCoder\Log;

use DevCoder\Log\Handler\HandlerInterface;
use Psr\Log\AbstractLogger;

class Logger extends AbstractLogger
{
    protected const DEFAULT_DATETIME_FORMAT = 'c';

    /**
     * @var HandlerInterface
     */
    private $handler;

    public function __construct(HandlerInterface $handler)
    {
        $this->handler = $handler;
    }

    public function log($level, $message, array $context = array())
    {
        $this->handler->handle([
            'message' => self::interpolate((string)$message, $context),
            'level' => strtoupper($level),
            'timestamp' => (new \DateTimeImmutable())->format(self::DEFAULT_DATETIME_FORMAT),
        ]);
    }

    protected static function interpolate(string $message, array $context = []): string
    {
        $replace = [];
        foreach ($context as $key => $val) {
            if (is_string($val) || method_exists($val, '__toString')) {
                $replace['{' . $key . '}'] = $val;
            }
        }
        return strtr($message, $replace);
    }
}
Enter fullscreen mode Exit fullscreen mode

We create a interface for handlers

<?php

namespace DevCoder\Log\Handler;

interface HandlerInterface
{
    public const DEFAULT_FORMAT = '%timestamp% [%level%]: %message%';
    public function handle(array $vars): void;
}

Enter fullscreen mode Exit fullscreen mode

Now we create a handler

<?php

namespace DevCoder\Log\Handler;

class FileHandler implements HandlerInterface
{
    /**
     * @var string
     */
    private $filename;

    public function __construct(string $filename)
    {
        $dir = dirname($filename);
        if (!file_exists($dir)) {
            $status = mkdir($dir, 0777, true);
            if ($status === false && !is_dir($dir)) {
                throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s"', $dir));
            }
        }
        $this->filename = $filename;
    }

    public function handle(array $vars): void
    {
        $output = self::DEFAULT_FORMAT;
        foreach ($vars as $var => $val) {
            $output = str_replace('%' . $var . '%', $val, $output);
        }
        file_put_contents($this->filename, $output . PHP_EOL, FILE_APPEND);
    }
}
Enter fullscreen mode Exit fullscreen mode

How to use ?

<?php

$logFileName = dirname(__DIR__) . DIRECTORY_SEPARATOR . 'var' . DIRECTORY_SEPARATOR . 'log' . DIRECTORY_SEPARATOR . date('Y-m-d') . '.log';

$handler = new \DevCoder\Log\Handler\FileHandler($logFileName);
$logger = new \DevCoder\Log\Logger($handler);

$logger->log(\Psr\Log\LogLevel::EMERGENCY, 'an error has occurred'); 

Enter fullscreen mode Exit fullscreen mode

Ideal for small project
Simple and easy!
https://github.com/devcoder-xyz/php-logging

Discussion (0)