Вызовите частные методы и частные свойства извне класса в PHP

Я хочу получить доступ к частным методам и переменным извне классов в очень редких случаях.

Я видел, что это невозможно, хотя интроспекция используется.

Конкретный случай следующий:

Я хотел бы иметь что-то вроде этого:

class Console { final public static function run() { while (TRUE != FALSE) { echo "\n> "; $command = trim(fgets(STDIN)); switch ($command) { case 'exit': case 'q': case 'quit': echo "OK+\n"; return; default: ob_start(); eval($command); $out = ob_get_contents(); ob_end_clean(); print("Command: $command"); print("Output:\n$out"); break; } } } } 

Этот метод должен быть введен в код следующим образом:

 Class Demo { private $a; final public function myMethod() { // some code Console::run(); // some other code } final public function myPublicMethod() { return "I can run through eval()"; } private function myPrivateMethod() { return "I cannot run through eval()"; } } 

(это просто одно упрощение: реальный идет через сокет и реализует кучу других вещей …)

Так…

Если вы создаете экземпляр класса Demo и вы вызываете $ demo-> myMethod (), вы получите консоль: эта консоль может получить доступ к первому методу, написав команду:

 > $this->myPublicMethod(); 

Но вы не можете успешно запустить второй:

 > $this->myPrivateMethod(); 

Есть ли у вас какие-либо идеи или существует ли какая-либо библиотека для PHP, которая позволяет вам это делать?

Большое спасибо!

    Просто сделайте этот метод общедоступным. Но если вы хотите запутаться, вы можете попробовать это (PHP 5.3):

     class LockedGate { private function open() { return 'how did you get in here?!!'; } } $object = new LockedGate(); $reflector = new ReflectionObject($object); $method = $reflector->getMethod('open'); $method->setAccessible(true); echo $method->invoke($object); 

    Первый вопрос, который вы должны задать, если вам нужно получить доступ к нему из-за пределов класса, почему вы объявили его закрытым? Если это не ваш код, у создателя, вероятно, есть веская причина объявить его закрытым, и доступ к нему напрямую – очень плохая (и в значительной степени не поддающаяся контролю) практика.

    EDIT : Как указывает Адам В. в комментариях, вы должны сделать доступный метод доступным до его вызова. Обновлен образец кода, чтобы включить это. Я еще не протестировал его, просто добавив сюда, чтобы сохранить ответ.

    Чтобы сказать это, вы можете использовать Reflection для этого. getMethod ReflectionClass , вызовите getMethod для метода, который вы хотите вызвать, а затем вызовите вызов на возвращаемом ReflectionMethod .

    Пример кода (хотя я его не тестировал, поэтому могут быть ошибки) может выглядеть так:

     $demo = new Demo(); $reflection_class = new ReflectionClass("Demo"); $reflection_method = $reflection_class->getMethod("myPrivateMethod"); $reflection_method->setAccessible(true); $result = $reflection_method->invoke($demo, NULL); 

    Ниже приведены варианты других ответов, которые можно использовать для создания таких вызовов в одной строке:

     public function callPrivateMethod($object, $methodName) { $reflectionClass = new \ReflectionClass($object); $reflectionMethod = $reflectionClass->getMethod($methodName); $reflectionMethod->setAccessible(true); $params = array_slice(func_get_args(), 2); //get all the parameters after $methodName return $reflectionMethod->invokeArgs($object, $params); } 

    У меня тоже есть эти проблемы, но я обойдусь этим по моим стандартам кодирования. Частные или защищенные функции обозначаются символом подчеркивания префикса, т.е.

     private function _myPrivateMethod() 

    Затем я просто делаю функцию общедоступной.

     public function _myPrivateMethod() 

    Таким образом, хотя функция является общедоступной, соглашение об именах дает уведомление о том, что публикация является частной и ее не следует использовать.

    Начиная с PHP 5.4 , вы можете использовать предопределенный класс Closure для привязки метода / свойства класса к дельта-функциям, имеющим доступ даже к частным членам.

    Класс Closure

    Например, у нас есть класс с частной переменной, и мы хотим получить к нему доступ за пределами класса:

     class Foo { private $bar = "Foo::Bar"; } 

    PHP 5.4+

     $foo = new Foo; $getFooBarCallback = function() { return $this->bar; }; $getFooBar = $getFooBarCallback->bindTo($foo, 'Foo'); echo $getFooBar(); // Prints Foo::Bar 

    Начиная с PHP 7, вы можете использовать новый метод Closure::call для привязки любого метода / свойства объекта obect к функции обратного вызова даже для частных членов:

    PHP 7+

     $foo = new Foo; $getFooBar = function() { return $this->bar; } echo $getFooBar->call($foo); // Prints Foo::Bar 

    Я думаю, что mirrorClass является единственной альтернативой, если вы действительно хотите выполнить некоторые частные методы. Во всяком случае, если вам просто нужен доступ для чтения к приватным или защищенным свойствам, вы можете использовать этот код:

     <?php class Demo { private $foo = "bar"; } $demo = new Demo(); // Will return an object with public, private and protected properties in public scope. $properties = json_decode(preg_replace('/\\\\u([0-9a-f]{4})|'.get_class($demo).'/i', '', json_encode((array) $demo))); ?> 

    Если вы можете добавить метод в класс, где этот метод определен, вы можете добавить метод, который использует call_user_method () внутренне. Это также работает с PHP 5.2.x

     <?php class SomeClass { public function callprivate($methodName) { call_user_method(array($this, $methodName)); } private function somePrivateMethod() { echo 'test'; } } $object = new SomeClass(); $object->callprivate('somePrivateMethod'); 

    Ответ ставится общедоступным для метода. Какой бы трюк вы ни делали, это было бы непонятно другим разработчикам. Например, они не знают, что в каком-то другом коде эта функция была доступна как общедоступная, посмотрев класс Demo.

    Еще кое-что. эта консоль может получить доступ к первому методу, написав команду, например:. Как это возможно? Консоль не может получить доступ к функциям демонстрационного класса, используя $ this.

    Почему вы не используете защищенные? И расширьте его