Вызовите частные методы и частные свойства извне класса в 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, которая позволяет вам это делать?
Спасибо большое!
Ответы
Ответ 1
Просто сделайте этот метод общедоступным. Но если вы хотите запутаться, вы можете попробовать это (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);
Ответ 2
Первый вопрос, который вы должны задать, если вам нужно получить доступ к нему из-за пределов класса, почему вы объявили его закрытым? Если это не ваш код, у создателя, вероятно, есть веская причина объявить его конфиденциальным, а доступ к нему напрямую - очень плохая (и в значительной степени не поддающаяся контролю) практика.
РЕДАКТИРОВАТЬ. Как указывает Адам В., в комментариях вам нужно сделать доступным доступ к закрытому методу перед его вызовом. Обновлен образец кода, чтобы включить это. Я еще не протестировал его, просто добавив сюда, чтобы обновить ответ.
Чтобы сказать об этом, вы можете использовать Reflection. Создайте ReflectionClass
, вызовите getMethod
для метода, который вы хотите вызвать, а затем вызовите invoke
в возвращаемом 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);
Ответ 3
Здесь варианты других ответов, которые могут быть использованы для того, чтобы сделать такие вызовы одной строкой:
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);
}
Ответ 4
Как и в случае с 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
Ответ 5
У меня тоже есть такие проблемы, но я обхожу это в своих стандартах кодирования. Частные или защищенные функции обозначаются символом подчеркивания префикса, т.е.
private function _myPrivateMethod()
Затем я просто делаю функцию общедоступной.
public function _myPrivateMethod()
Итак, хотя функция общедоступна, соглашение об именах дает уведомление о том, что публикация является частной и ее не следует использовать.
Ответ 6
Я думаю, что 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)));
?>
Ответ 7
Если вы можете добавить метод в класс, где этот метод определен, вы можете добавить метод, который использует 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');
Ответ 8
Ответ ставится общедоступным для метода. Какой бы трюк вы ни делали, это было бы непонятно другим разработчикам. Например, они не знают, что в каком-то другом коде эта функция была доступна как общедоступная, посмотрев класс Demo.
Еще одна вещь. , что консоль может получить доступ к первому методу, написав команду, например:. Как это возможно? Консоль не может получить доступ к функциям демонстрационного класса, используя $this.
Ответ 9
Почему вы не используете защищенные? И расширьте его