「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) );
プロパティをダイレクトにやりとりする事は基本やらないので、メソッドベースだとこの辺があれば「とりあえず」かなぁ、的な。
*1:事実だが