103 |
- |
1 |
# Extending Monolog
|
|
|
2 |
|
|
|
3 |
Monolog is fully extensible, allowing you to adapt your logger to your needs.
|
|
|
4 |
|
|
|
5 |
## Writing your own handler
|
|
|
6 |
|
|
|
7 |
Monolog provides many built-in handlers. But if the one you need does not
|
|
|
8 |
exist, you can write it and use it in your logger. The only requirement is
|
|
|
9 |
to implement `Monolog\Handler\HandlerInterface`.
|
|
|
10 |
|
|
|
11 |
Let's write a PDOHandler to log records to a database. We will extend the
|
|
|
12 |
abstract class provided by Monolog to keep things DRY.
|
|
|
13 |
|
|
|
14 |
```php
|
|
|
15 |
<?php
|
|
|
16 |
|
|
|
17 |
use Monolog\Logger;
|
|
|
18 |
use Monolog\Handler\AbstractProcessingHandler;
|
|
|
19 |
|
|
|
20 |
class PDOHandler extends AbstractProcessingHandler
|
|
|
21 |
{
|
|
|
22 |
private $initialized = false;
|
|
|
23 |
private $pdo;
|
|
|
24 |
private $statement;
|
|
|
25 |
|
|
|
26 |
public function __construct(PDO $pdo, $level = Logger::DEBUG, $bubble = true)
|
|
|
27 |
{
|
|
|
28 |
$this->pdo = $pdo;
|
|
|
29 |
parent::__construct($level, $bubble);
|
|
|
30 |
}
|
|
|
31 |
|
|
|
32 |
protected function write(array $record)
|
|
|
33 |
{
|
|
|
34 |
if (!$this->initialized) {
|
|
|
35 |
$this->initialize();
|
|
|
36 |
}
|
|
|
37 |
|
|
|
38 |
$this->statement->execute(array(
|
|
|
39 |
'channel' => $record['channel'],
|
|
|
40 |
'level' => $record['level'],
|
|
|
41 |
'message' => $record['formatted'],
|
|
|
42 |
'time' => $record['datetime']->format('U'),
|
|
|
43 |
));
|
|
|
44 |
}
|
|
|
45 |
|
|
|
46 |
private function initialize()
|
|
|
47 |
{
|
|
|
48 |
$this->pdo->exec(
|
|
|
49 |
'CREATE TABLE IF NOT EXISTS monolog '
|
|
|
50 |
.'(channel VARCHAR(255), level INTEGER, message LONGTEXT, time INTEGER UNSIGNED)'
|
|
|
51 |
);
|
|
|
52 |
$this->statement = $this->pdo->prepare(
|
|
|
53 |
'INSERT INTO monolog (channel, level, message, time) VALUES (:channel, :level, :message, :time)'
|
|
|
54 |
);
|
|
|
55 |
|
|
|
56 |
$this->initialized = true;
|
|
|
57 |
}
|
|
|
58 |
}
|
|
|
59 |
```
|
|
|
60 |
|
|
|
61 |
You can now use this handler in your logger:
|
|
|
62 |
|
|
|
63 |
```php
|
|
|
64 |
<?php
|
|
|
65 |
|
|
|
66 |
$logger->pushHandler(new PDOHandler(new PDO('sqlite:logs.sqlite')));
|
|
|
67 |
|
|
|
68 |
// You can now use your logger
|
|
|
69 |
$logger->addInfo('My logger is now ready');
|
|
|
70 |
```
|
|
|
71 |
|
|
|
72 |
The `Monolog\Handler\AbstractProcessingHandler` class provides most of the
|
|
|
73 |
logic needed for the handler, including the use of processors and the formatting
|
|
|
74 |
of the record (which is why we use ``$record['formatted']`` instead of ``$record['message']``).
|
|
|
75 |
|
|
|
76 |
← [Utility classes](03-utilities.md)
|