読者です 読者をやめる 読者になる 読者になる

HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

ログの出力

PHP

デバッグやその他の目的で、様々な情報をログファイルに書き出したりすることがあるが、使用する方法によっていろいろと違いがあるようなので、ちょっと整理してみるテスト(謎)。

単純な値を出力する

例えばこんなの。

<?php
$logMsg = "This is a log message.";
$errorCode = 54321;

ログ出力のやりようはいくらでも。

<?php
// fprintfでファイルに。
$fp = fopen("/path/to/logfile", "a");
fprintf($fp, "%04d:%06d:%s\n", __LINE__, $errorCode, $logMsg);
fclose($fp);

// 整形はsprintfで。
$fp = fopen("/path/to/logfile", "a");
$msg = sprintf("%04d:%06d:%s\n", __LINE__, $errorCode, $logMsg);
fprintf($fp, "%s", $msg);
fclose($fp);

// error_log関数でファイルに。
$msg = sprintf("%04d:%06d:%s\n", __LINE__, $errorCode, $logMsg);
error_log($msg, 3, "/path/to/logfile");

まぁ、あらゆるものを調べようと思ってもきりがなさそうなのでこんなところで。

ログメッセージを作る

文字列や整数など、シンプルなものをログ出力するならいいのだが、ログ出力したいデータはより複雑であることが多い。
例えば、こんなの。

<?php
class Hoge {
    private $var1;
    protected $var2;
    public $var3;
    public function __construct($msg) {
        $this->var1 = 'private:' . $msg;
        $this->var2 = 'protected:' . $msg;
        $this->var3 = 'public:' . $msg;
    }
}
$vAry = array(
    "v1" => "123",
    "v2" => "0",
    "v3" => "abc",
    "v4" => "",
    "v5" => null,
    "v6" => array(),
    "v7" => array("a", "b", "c"),
    "v8" => 123,
    "v9" => 0,
    "v10" => true,
    "v11" => false,
    "v12" => new Hoge('hello world'),
);
単純な値と同じ扱いをしてみる
<?php
$msg = $vAry;
printf("%s\n", $msg);

出力はこんな感じ。

Array

いうまでもなく、まったく役に立たない。

print_r関数を使う

print_r関数は、配列やオブジェクトまで考慮した出力用関数。第二引数にtrueを渡すと、標準出力に書き出す代わりに文字列として返してくれる。

<?php
$msg = print_r($vAry, true);
printf("%s\n", $msg);

出力はこんな感じ。

Array
(
    [v1] => 123
    [v2] => 0
    [v3] => abc
    [v4] =>
    [v5] =>
    [v6] => Array
        (
        )

    [v7] => Array
        (
            [0] => a
            [1] => b
            [2] => c
        )

    [v8] => 123
    [v9] => 0
    [v10] => 1
    [v11] =>
    [v12] => Hoge Object
        (
            [var1:Hoge:private] => private:hello world
            [var2:protected] => protected:hello world
            [var3] => public:hello world
        )

)

中身がある程度分かっているものになら使えるが、例えば"v1"と"v8"は、見た目上は同じ「123」なのだが、実際には前者は文字列型、後者は整数型であるので、そこまでの区別が必要なケースでは使えない。また、空文字列、null、falseの区別がつかないのも、場合によっては危ないかも。

var_dump関数を使う

var_dump関数は、詳細な情報が出力されるので、デバッグにはもってこいなのだが、標準出力にしか出力ができないので、ログファイルに書き出そうと思ったらちょっとひと手間必要。

<?php
ob_start();
var_dump($vAry) ;
$msg = ob_get_contents();
ob_end_clean();
printf("%s\n", $msg);

出力はこんな感じ。

array(12) {
  ["v1"]=>
  string(3) "123"
  ["v2"]=>
  string(1) "0"
  ["v3"]=>
  string(3) "abc"
  ["v4"]=>
  string(0) ""
  ["v5"]=>
  NULL
  ["v6"]=>
  array(0) {
  }
  ["v7"]=>
  array(3) {
    [0]=>
    string(1) "a"
    [1]=>
    string(1) "b"
    [2]=>
    string(1) "c"
  }
  ["v8"]=>
  int(123)
  ["v9"]=>
  int(0)
  ["v10"]=>
  bool(true)
  ["v11"]=>
  bool(false)
  ["v12"]=>
  object(Hoge)#1 (3) {
    ["var1":"Hoge":private]=>
    string(19) "private:hello world"
    ["var2":protected]=>
    string(21) "protected:hello world"
    ["var3"]=>
    string(18) "public:hello world"
  }
}

ちょっとした用途には不向きだが、本当に必要であればユーティリティ化してしまえばよいかなという感じ。標準出力に出してOKな場面では、var_dump関数単体では一番よく使っているかも。

var_export関数を使う

var_exportはprint_rと同様に、第二引数にtrueを指定することで、出力内容を文字列として取得することができる。出力される形式は、PHPのコードにそのまま使える形(らしい)。

<?php
$msg = var_export($vAry, true);
printf("%s\n", $msg);

出力はこんな感じ。

array (
  'v1' => '123',
  'v2' => '0',
  'v3' => 'abc',
  'v4' => '',
  'v5' => NULL,
  'v6' =>
  array (
  ),
  'v7' =>
  array (
    0 => 'a',
    1 => 'b',
    2 => 'c',
  ),
  'v8' => 123,
  'v9' => 0,
  'v10' => true,
  'v11' => false,
  'v12' =>
  Hoge::__set_state(array(
     'var1' => 'private:hello world',
     'var2' => 'protected:hello world',
     'var3' => 'public:hello world',
  )),
)

出力の内容から、数値、文字列、真偽値、オブジェクト、nullの区別はできるので、バランス的には一番使いやすいのかな、と思う。