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)