CakePHP4で色々ログを出したい

CakePHP4で色々ログを出したい

CakePHP4にはLogクラスが準備されているので、それを使えばログ出力できます。
ログ自体はlogsディレクトリ配下に、通常はエラーレベルによってerror.logかdebug.logのどちらかにログが出力されます。

なのですが「ResultSetInterfaceのログ取りたい」というような時は高確率でエラーになります。
ログを出そうとしているのにエラーとか意味がわかりません。
今回はLogクラスをちょっとイジって何も考えずにログ出力する手順の説明になります。

<今回の実行環境>
CakePHP4.2.4
PHP7.4

DBは使用しませんので割愛します。

Logクラスの仕組み

そもそもの話なんですが、Logクラスを使用してログ出力をする際は「string型」じゃないと出力できないようになっています。
だからResutSetInterfaceとかEntityInterfaceとかを出力しようとするとエラーになるわけです。

実際にコアファイルを見てみましょう。
CakePHP4はインストールしているものとして、以下のファイルを参照します。
vendor/cakephp/cakephp/src/Log/Log.phpがそれです。


public static function info(string $message, $context = []): bool 
{ 
    return static::write(__FUNCTION__, $message, $context); 
}

通常だと「Log::info();」で出力する部分ですね。
コメントは端折ってますが、パラメータの型を見るとstringと書いてあります。
ですので、出力したい内容をstringで渡してあげれば良さそうです。

Log出力したい内容をstringで渡す

キャストするとかあるとは思いますが、一番ラクなのは「print_r();」を使用することです。

昔、PHPを始めた頃はprint_r();とechoでしかデバッグしてませんでした。
時は流れて今ではdd();とdump();を駆使するようになりました。大いなる進歩です。
xdebugとかそういう類は特に使いません。意識低いエンジニアですので仕方ありません。

さておき、以下がサンプルです。


    // usersモデルからデータ取得 
    $resulSetInterface = $this->user->find();

    // ログに出力 
    Log::debug(print_r($resultSetInterface, true));

実行結果はまた端折りますが、logs/debug.logに取得した結果が出力されていると思います。
非常に単純な小ネタです。

ログ出力をクラスにしてみる

前述のprint_r();するだけの小ネタ部分をクラスにします。
クラスにしておくと何かと便利な機会は多いですし。

自分はよくこういうのをクラスにしてしまいます。
開発中はログを見る機会はあると思いますし、本当にヤバいものはログに残したいでしょうし。

クラスを作る場所ですが、お好きな場所でいいかと思います。
自分はtraitでこういうクラスを作り、AppController.phpのような基底クラスでuseするのが好きですがこの辺は好みの話です。

実装自体は大したことないです。
意識低いのでLogクラスをそのままコピって加工するだけです。

<?php
declare(strict_types=1);

namespace App\Traits;

use Cake\Datasource\ResultSetInterface;
use Cake\Log\Log;
use Psr\Log\LogLevel;

/**
 * ログ出力Trait
 *
 * 文字列だけではなく配列/ResultSetInterface/Entity等もログ出力可能
 *
 * @package App\Utility
 */
trait LoggerTrait
{
    /**
     * 文字列ログ出力
     *
     * パラメータで取得した文字列をログ出力
     * 文字列/配列/ResultSetInterfaceをパラメータとして指定可能
     * ログレベルに応じて出力されるログファイルが変更される
     *
     * @param string|array|ResultSetInterface $message   ログに書き込むメッセージ
     * @param string $level ログレベル(デフォルトはdebug.logに出力)
     * @param array $context    ログスコープ
     * @return bool
     */
    public function output($message, $level = LogLevel::DEBUG, $context = []): bool
    {
        return Log::write($level, print_r($message, true), $context);
    }
}

上のサンプルはtraitで作成しているので、このtraitをAppController.phpでuseしておくとあとは「$this->output();」でログ出力できるというだけの話です。
namespaceが「Traits」になっている理由は予約語なのか「Trait」をnamespaceとして使用できないためです。

ただ上記の場合だとログレベルを変える時に文字列で指定する必要がありますので、Psr\Log\LogLevelを呼び元でuseするか、定数クラスに別途宣言するとかそういうのをするといいかと思います。

まとめ

上記のようなことをすると、とりあえず何でもログ出力できるという小ネタでした。クラスまで作る必要あるのかどうかはさておきですが、こういうクラスを作っておいてプロダクト開発でのルールにしておくと後々見やすくなったりします。
各人、思い通りに作成するとまぁまぁカオスになりますので。

以上がCakePHP4で色々ログを出す手順の説明になります。
お疲れ様でした。

CakePHP4カテゴリの最新記事