この記事は最終更新日から2年以上経過しており、内容が古くなっている可能性があります。
ご理解の上、記事を閲覧いただければと思います。

CakePHPで記録されるログ(監査ログやログイン履歴)は、通常logsフォルダにテキストファイルとして保存されます。

しかし、それらのログ情報はデータベースにロギングしたほうが利用や閲覧の際に便利です。

そこで今回はデータベースログアダプターを自作する方法を紹介します。
※検証動作環境は「CakePHP 3.4.9」。

1. 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{
}

2. データベースログアダプターを作成する

次に、ロギング処理に必要なログアダプターを作成し、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);
    }

}

3. ロギング設定を変更する

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

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

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

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

4. ログへの書き込みを行う

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

use Cake\Log\Log;

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

5. 最後にログが書き込まれているか確認する

mysqlコマンドで確認し、以下のようにログが書き込まれていればOKです。

cakephpロギング結果


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

参考書籍
PHPフレームワーク Laravel入門

PHPフレームワーク Laravel入門

掌田津耶乃
7,255円(04/20 18:26時点)
Amazonの情報を掲載しています