<rmcreative>

RSS

Вызвать private метод класса в PHP

25 мая 2015

Бывает, не хочется портить API ради тестирования, но нужно как-то добраться до private метода. Сделать это можно вот так:

function callPrivateMethod($object, $method, $args)
{
    $classReflection = new \ReflectionClass(get_class($object));
    $methodReflection = $classReflection->getMethod($method);
    $methodReflection->setAccessible(true);
    $result = $methodReflection->invokeArgs($object, $args);
    $methodReflection->setAccessible(false);
    return $result;
}
 
$myObject = new MyClass();
callPrivateMethod($myObject, 'hello', ['world']);

UPD: вариант без Reflection

Комментарии RSS

  1. №9803
    Павел
    Павел 26 мая 2015 г., 0:21:55

    Если метод private или protected, то скорее всего он вызывается в другом каком-то методе имеющий доступ public. И тестировать его следует именно через открытый метод. Рефлексировать в любой непонятной ситуации -- гон.

  2. №9804
    Жора
    Жора 26 мая 2015 г., 1:07:02

    Павел, а если это какой-нибудь внутренний счетчик для которого не хочется делать геттер чтобы код не разрастался?

  3. №9805
    Жора
    Жора 26 мая 2015 г., 1:08:03

    Ведь так же можно и до всяких приватных переменных добираться что может быть удобно

  4. №9806
    Sam
    Sam 26 мая 2015 г., 2:11:51

    Павел, ситуация следующая: открытый метод на основе доступности PECL-расширения выбирает, использовать ли это расширение или же откатиться на fallback-метод, написанный на PHP. Открывать этот fallback-метод смысла никакого нет. Прогонять два PHP: с расширением и без, не хочется.

  5. №9808
    Павел
    Павел 26 мая 2015 г., 12:00:41

    Не, ребят, я понимаю, что есть исключительные ситуации когда без рефлексии никак. Я вел к тому, что не стоит ее юзать всегда и где ни попадя.

  6. №9809
    Roman
    Roman 26 мая 2015 г., 12:16:45

    Ещё вариант, с версий где есть call у Closure 3v4l.org/abZ3Y

  7. №9813
    klay
    klay 26 мая 2015 г., 16:38:12

    А всякие моки не рефлексию мучают случем? :)

  8. №9814
    klay
    klay 26 мая 2015 г., 17:48:05

    Roman, только php7 ?

  9. №9815
    Nicolai
    Nicolai 26 мая 2015 г., 23:15:44

    Ошибочка

    $classReflection = new \ReflectionClass(get_class($myClass));
    Вместо
     $classReflection = new \ReflectionClass(get_class($object);
  10. №9816
    Sam
    Sam 27 мая 2015 г., 2:34:20

    Поправил.

  11. №9825
    Andrey
    Andrey 28 мая 2015 г., 10:28:40

    А для чего $result?

  12. №9827
    Sam
    Sam 28 мая 2015 г., 16:21:10

    Хе-хе. Добавил return.

  13. №9837
    nitso
    nitso 10 июня 2015 г., 12:46:44

    Klay, моки (в PHPUnit) генерируют код для класса-обертки, а потом его eval'ят.

    Можно еще вместо

    $classReflection = new \ReflectionClass(get_class($myClass));

    использовать

    $objectReflection = new \ReflectionObject($myClass);

    Остальные операции такие же.

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.