「PHPでprivateなメソッドを外から叩く時ってどうやるんだっけ?」で、リフレクションって単語をしょっちゅう忘れるから「それの備忘録用」って見方をしないように*1。
さっきもまぁ「リダイレクト……リファラー……り……り……」で、そこそこ悩んでたのは秘密だ。
おいといて。
protectedだと割と本当に色々あって、一番雑なのが
・テスト用に継承クラス作る
ってやりかた。
<?php
declare(strict_types=1);
// テスト対象のクラス
class TestTarget {
protected function t()
{
return mt_rand(1, 10);
}
}
// テスト用クラス
class Test extends TestTarget
{
public function h() {
return $this->t();
}
}
//
$obj = new Test();
var_dump( $obj->h() );
PHP7の無名クラス使うなら
<?php
declare(strict_types=1);
// テスト対象のクラス
class TestTarget {
protected function t()
{
return mt_rand(1, 10);
}
}
// テスト用クラス
$obj = new class extends TestTarget {
public function h() {
return $this->t();
}
};
var_dump( $obj->h() );
これでもOK。
この辺りだと、staticなメソッドでも自由自在。
継承クラス書いてもよいし、無名クラス使うんなら
<?php
declare(strict_types=1);
// テスト対象のクラス
class TestTarget {
protected static function t()
{
return mt_rand(1, 10);
}
}
// テスト用クラス
$obj = new class extends TestTarget {
public function h() {
return static::t();
}
};
var_dump( $obj->h() );
とも書ける。
……で片付けたいので、正直「メソッドはprivateにすんな面倒だ」って、色々な角度から思う。
んだけど、まぁ「時すでに遅し」なケースもあろうかと思うので、少しだけ考察。
普通のメソッドなら、ReflectionMethodのsetAccessible()が手っ取り早いっつか綺麗だとは思う。
<?php
declare(strict_types=1);
// テスト対象のクラス
class TestTarget {
private function t()
{
return mt_rand(1, 10);
}
}
//
$m = new ReflectionMethod('TestTarget', 't');
$m->setAccessible(true);
var_dump( $m->invoke(new TestTarget) );
なお実はstaticも普通にいける。
<?php
declare(strict_types=1);
// テスト対象のクラス
class TestTarget {
private static function t()
{
return mt_rand(1, 10);
}
}
//
$m = new ReflectionMethod('TestTarget', 't');
$m->setAccessible(true);
var_dump( $m->invoke(new TestTarget) );
プロパティをダイレクトにやりとりする事は基本やらないので、メソッドベースだとこの辺があれば「とりあえず」かなぁ、的な。