前回の続き。
runkitにはクラスに対しても色々やっちゃうことが可能です。
<?php
// クラス
class A{ public static function getName(){print('A');} }
class B{ public static function getName(){print('B');} }
class C extends A{}
print(C::getName()); // A
runkit_constant_add('C::hoge', 1);
print(C::hoge); // 1
runkit_class_emancipate('C');
print(C::getName()); // Fatal error: Call to undefined method C::getName()
runkit_class_adopt('C', 'B');
print(C::getName()); // B
クラス定数やメソッドの追加削除に留まらず、親クラス入れ替えなんて芸当もできてしまいます。
ここでは前やったprivateな__construct()呼び出しを、runkitを使ってやってみます。
<?php
class HOGE{
public $value = 0;
private function __construct(){
$this->value = 1;
}
}
runkit_method_rename('HOGE', '__construct', 'construct');
runkit_method_add('HOGE', '__construct', '', '$this->construct();', RUNKIT_ACC_PUBLIC);
$hoge = new HOGE();
print $hoge->value; // 1
クラスを書き換えた結果、最終的にはこういう形になっていると思われます。
<?php
class HOGE{
public $value = 0;
public function __construct(){
$this->construct();
}
private function construct(){
$this->value = 1;
}
}
これならごく自然にnewできますね。
いいのかそれ。
なお、最近のPHP関数は引数にクロージャを受け付けてくれるものが多いですが、runkit_method_add()等は文字列しか駄目なようです。
runkitはあまりに強力すぎるため、実環境で使うことはまず無いでしょう。
こんな風に遊んでみるくらいならともかく、仕事でこんなことをやられたらたまったものではありません。