Я хочу получить доступ к закрытым методам и переменным снаружи классов в очень редких конкретных случаях.
Я видел, что это не быть возможным, хотя самоанализ используется.
Конкретный случай является следующим:
Я хотел бы иметь что-то вроде этого:
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-> 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);
Первый вопрос, который вы должны задать: если вам нужно получить к нему доступ извне класса, почему вы объявили его закрытым? Если это не ваш код, то у создателя, вероятно, была веская причина объявить его закрытым, и доступ к нему напрямую является очень плохой (и в значительной степени неподдерживаемой) практикой.
РЕДАКТИРОВАТЬ : Как указывает Адам В. в комментариях, вам необходимо сделать закрытый метод доступным перед его вызовом. Образец кода обновлен, чтобы включить это. Я не тестировал его - просто добавляю сюда, чтобы держать ответ в актуальном состоянии.
Как уже было сказано, вы можете использовать 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);
У меня есть эти проблемы тоже иногда, но я обхожу их через свои стандарты кодирования. Частные или защищенные функции обозначаются префиксом подчеркивания, т.е.
private function _myPrivateMethod()
Тогда я просто делаю функцию общедоступной.
public function _myPrivateMethod()
Таким образом, хотя функция является общедоступной, соглашение об именах уведомляет о том, что в то время как общедоступная функция является частной и ее не следует использовать.