privateやprotectedなプロパティに値を設定したり、値を取得する場合、ReflectionPropertyクラスを使用します。 同様に、pivateやprotectedのメソッドを実行する場合、ReflectionMethodを使用します。 ユニットテストでこれらを使うと、ユニットテストのためだけにpublicにする必要がなくなります。

参考 ユニットテスト用支援クラスのサンプル

メソッド

ReflectionMethodクラスを使用して、PrivateとProtectedなメソッドを実行する方法。 手順は以下になります。

  • ReflectionMethodのインスタンス作成
  • setAccessibleメソッドでアクセス許可にする
  • invokeメソッドで、publicでないメソッドを実行

参照

サンプルは以下のようになります。

<?php

class Calc {
    private function add($a, $b)
    {
        return $a + $b;
    }

    protected function max($a, $b)
    {
        return $a >= $b ? $a : $b;
    }
}

$calc = new Calc();

// private method
$method = new ReflectionMethod($calc,  'add');
$method->setAccessible(true);
$result = $method->invoke($calc, 3, 4);
var_dump($result);  // 結果は7

// protected method
$method = new ReflectionMethod($calc, 'max');
$method->setAccessible(true);
$result = $method->invoke($calc, 3, 4);
var_dump($result);   // 結果は4
PrivateやProtectedの場合、setAccessible(true)が無いと、invokeメソッドの実行箇所でエラーになります。

プロパティ

ReflectionPropertyクラスを使用して、PrivateとProtectedなプロパティの値を取得したり、変更する方法。 手順は以下になります。

  • ReflectionPropertyのインスタンス作成
  • setAccessibleメソッドでアクセス許可にする
  • getValueまたはsetValueメソッドを実行

参照

サンプルは以下のようになります。

<?php

class Book {
    private $title;
    protected $price;

    public function __construct($title, $price) {
        $this->title = $title;
        $this->price = $price;
    }

    public function getTitle() {
        return $this->title;
    }

    public function getPrice() {
        return $this->price;
    }
}


$book = new Book('タイトル', 1080);

$propTitle = new ReflectionProperty(get_class($book), 'title');
$propPrice = new ReflectionProperty(get_class($book), 'price');

// アクセス許可を設定
$propTitle->setAccessible(true);
$propPrice->setAccessible(true);

var_dump($propTitle->getValue($book));     // 実行結果:  string(12) "タイトル"
var_dump($propPrice->getValue($book));     // 実行結果:  int(1080)

$propTitle->setValue($book, '修正タイトル');
$propPrice->setValue($book, 2160);

var_dump($propTitle->getValue($book));     // 実行結果:  string(18) "修正タイトル"
var_dump($propPrice->getValue($book));     // 実行結果:  int(2160)