PHPでデバック出力に最適なのは何か

f:id:nomunomu0504:20190411144524j:plain:w0

開発する上で変数内に格納されているデータを確認することはしばしばあります。

このとき、何で表示するのが一番いいのでしょうか。いろいろ見ていきます

var_dump

void var_dump ( mixed $expression [, mixed $... ] )

この関数は、指定した式に関してその型や値を含む構造化された情報を 返します。配列の場合、その構造を表示するために各値について再帰的に 探索されます。

オブジェクトのすべての public、private および protected なプロパティが出力されます。ただし、そのオブジェクトが __debugInfo() メソッド (PHP 5.6.0 で追加> されました) を実装している場合は、その限りではありません。

PHP: var_dump - Manual

以下が使用例です。

<?php
$a = array(1, 2, array("a", "b", "c"));
var_dump($a);
array(3) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  array(3) {
    [0]=>
    string(1) "a"
    [1]=>
    string(1) "b"
    [2]=>
    string(1) "c"
  }
}

__debugInfo()

このメソッドは、var_dump() がオブジェクトをダンプするときに、 プロパティの情報を取得するために呼ばれます。 もしオブジェクトにこのメソッドが定義されていなければ、 すべての public, protected, private プロパティを表示します。

PHP: マジックメソッド - Manual

これは”マジックメソッド”と言われ、このメソッドが定義してあるオブジェクトは出力結果を自由に変えることができます。

<?php
class ManyCalc {
    private $num;

    public function __construct($val) {
        $this->num = $val;
    }

    public function __debugInfo() {
        return [
            'plus'    => $this->num + 10,
            'minus'   => $this->num - 10,
            'times'   => $this->num * 10,
            'divided' => $this->num / 10
        ];
    }
}

var_dump(new ManyCalc(10));
?>

この結果、出力は以下のようになります

object(ManyCalc)#1 (1) {
  ["plus"]=>
  int(20)
  ["minus"]=>
  int(0)
  ["times"]=>
  int(100)
  ["divided"]=>
  int(1)
}

var_export

mixed var_export ( mixed $expression [, bool $return = FALSE ] )

var_export() は、 渡された変数に関する構造化された情報を返します。この関数は var_dump() に似ていますが、 返される表現が有効な PHP コードであるところが異なります。

PHP: var_export - Manual

通常通り、変数等の出力に使う場合には以下の通りです

<?php
$a = array (1, 2, array ("a", "b", "c"));
var_export($a);
?>
array (
  0 => 1,
  1 => 2,
  2 =>
  array (
    0 => 'a',
    1 => 'b',
    2 => 'c',
  ),
)

ただ、var_export$return = trueとすることで、変数にそのまま代入することができる

<?php
$b = 3.1;
$v = var_export($b, true);
echo $v;
3.1

またPHP5.1.0からはクラスのエクスポートも可能になりました。また、var_dump同様__set_stateメソッドを実装することで、出力を編集することができます。

<?php
class A { public $var; }
$a = new A;
$a->var = 5;
var_export($a);
?>
A::__set_state(array(
   'var' => 5,
))

__set_state()

<?php
class A
{
    public $var1;
    public $var2;

    public static function __set_state($an_array)
    {
        $obj = new A;
        $obj->var1 = $an_array['var1'];
        $obj->var2 = $an_array['var2'];
        return $obj;
    }
}

$a = new A;
$a->var1 = 5;
$a->var2 = 'foo';

eval('$b = ' . var_export($a, true) . ';'); // $b = A::__set_state(array(
                                            //    'var1' => 5,
                                            //    'var2' => 'foo',
                                            // ));
var_dump($b);
?>
object(A)#2 (2) {
  ["var1"]=>
  int(5)
  ["var2"]=>
  string(3) "foo"
}

このようにすることで、自由度の高い出力方式を構築することができます。

mixed print_r ( mixed $expression [, bool $return = FALSE ] )

print_r()、var_dump() および var_export() は、オブジェクトの protected および private のプロパティも表示します。 静的なクラスメンバーは表示されません。

PHP: print_r - Manual

<?php
$a = array ('a' => 'apple', 'b' => 'banana', 'c' => array ('x', 'y', 'z'));
print_r ($a);
?>
Array
(
    [a] => apple
    [b] => banana
    [c] => Array
        (
            [0] => x
            [1] => y
            [2] => z
        )
)

また$return = trueにすることで、出力を変数に代入することができます。

$b = array ('m' => 'monkey', 'foo' => 'bar', 'x' => array ('x', 'y', 'z'));
$results = print_r($b, true); // print_r の結果が $results に格納される

おまけ

var_dumpなどは<pre>タグで整形して表示させることがほとんどだと思います。なので以下のような関数を定義しておくといいと思います。

<?
function va($val) {
    echo '<pre>';
    var_dump($val);
    echo '</pre>';
}