CakePHP3でデータベースロギング

CakePHPで記録されるログは通常logsフォルダにテキストファイルとして保存されます。しかし、監査ログやログイン履歴などの情報はデータベースにロギングしたほうが便利なので、データベースログアダプターを自作してみます。

【動作環境】CakePHP 3.4.9

logsテーブルの作成

まずはじめに、ログ記録する「logs」テーブルを作成します。

CREATE TABLE logs (
  id int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  datetime datetime NOT NULL,
  level varchar(10) NOT NULL,
  message text,
  PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

エンティティークラス・テーブルクラスの作成

logsテーブルのエンティティークラス・テーブルクラスも作成しておきます。

<?php

namespace App\Model\Entity;

use Cake\ORM\Entity;

class Log extends Entity
{

    protected $_accessible = [
        '*' => false,
        'datetime' => true,
        'level' => true,
        'message' => true,
    ];

}
<?php

namespace App\Model\Table;

use Cake\ORM\Table;

class LogsTable extends Table{
}

データベースログアダプターの作成

次にロギング処理に必要なログアダプターを作成します。
ログアダプターはsrc/Log/Engine/DatabaseLog.phpに置きます。

<?php

namespace App\Log\Engine;

use Cake\Log\Engine\BaseLog;
use Cake\ORM\TableRegistry;

class DatabaseLog extends BaseLog
{

    protected $_defaultConfig = [
        'types' => null,
        'levels' => [],
        'scopes' => [],
        'table' => null,
    ];

    protected $_table = null;

    public function __construct(array $config = [])
    {
        parent::__construct($config);
        if (empty($this->_config['table'])) {
            $this->_config['table'] = 'Logs';
        }
        $this->_table = TableRegistry::get($this->_config['table']);
    }

    public function log($level, $message, array $context = [])
    {
        $entity = $this->_table->newEntity([
            'datetime' => date('Y-m-d H:i:s'),
            'level' => $level,
            'message' => $this->_format($message, $context),
        ]);
        $this->_table->save($entity);
    }

}

ロギング設定

データベースロギングを有効にするため、ロギング設定を変更します。初期設定のdebugとerrorはコメントアウトして、ファイルロギングを無効化しておきます。

    /**
     * Configures logging options
     */
    'Log' => [
        //'debug' => [
        //    ...
        //],
        //'error' => [
        //    ...
        //],
        'database' => [
            'className' => 'App\Log\Engine\DatabaseLog',
            'table' => 'Logs', //テーブル名
            'levels' => [], //記録するログレベル
        ],
    ],

今回は'levels' => []としているため、全てのログレベルが記録されます。一部のログレベルのみ記録したい場合は'levels' => ['warning', 'error', 'critical', 'alert', 'emergency']のように記述します。

これでデータベースロギングの準備完了です。

ログへの書き込み

あとは通常のロギングと同じように Cake\Log\Log::write() を使用してログを書き込みます。(詳しくはCakePHP3 Cookbook ロギングに記載があります。)

use Cake\Log\Log;

Log::write('error', 'エラーが発生しました');

ログが書き込まれているか確認

mysqlコマンドで確認したら、ちゃんとログが書き込まれていました。

このデータベースロギングを応用して、ユーザーID・IPアドレスを記録して監査ログを取ったり、管理画面からログ検索できるようにしたりすると便利かもしれません。

PHPフレームワーク Laravel入門

PHPフレームワーク Laravel入門

掌田津耶乃
3,240円(05/26 10:39時点)
発売日: 2017/09/16
Amazonの情報を掲載しています