<rmcreative>

RSS

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

10 июня 2015

В комментариях к заметке о вызове private метода через Reflection Roman верно подметил, что можно использовать вместо Reflection анонимные функции. Вот только его вариант работает с PHP7.

Оказывается, можно проделать такое чуть иначе и в PHP 5.4:

class PrivacyViolator
{
    private $caller;
 
    function __construct()
    {
        $this->caller = function ($method, $args) {
            return call_user_func_array([$this, $method], $args);
        };
    }
 
    function callPrivateMethod($object, $method, $args)
    {
        return $this->caller->bindTo($object, $object)->__invoke($method, $args);
    }
}
 
$myObject = new MyClass();
$privacyViolator = new PrivacyViolator();
$privacyViolator->callPrivateMethod($myObject, 'hello', ['world']);

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

  1. №9838
    Sam
    Sam 10 июня 2015 г., 23:45:26

    Оказывается, вопрос давно изучен Marco Pivetta. Ещё и с замерами скорости.

  2. №9839
    klay
    klay 11 июня 2015 г., 11:50:40

    php.net/manual/ru/closure.bindto.php

    $this->caller->bindTo($object);

    Второй $object лишний

  3. №9840
    Sam
    Sam 11 июня 2015 г., 12:14:43

    Нет, не лишний. scope как раз и надо менять.

  4. №9841
    klay
    klay 11 июня 2015 г., 12:22:17

    Ох, да, не внимательно прочёл.

  5. №9842
    Максим
    Максим 11 июня 2015 г., 17:50:23

    Понятия не имею когда это может пригодиться :) Разве что джуниорам показать как не надо писать код.

  6. №9843
    Sam
    Sam 11 июня 2015 г., 21:37:07

    В тестах.

  7. №9844
    ElisDN
    ElisDN 12 июня 2015 г., 3:14:13

    Функция с $this закидывается в объект и работает изнутри. Да, классно! Но до методов родительского класса добраться не получится. Хотя если бы она могла саму себя прокинуть в parent... но $this в объекте только один.

  8. №9849
    romanitalian
    romanitalian 24 июня 2015 г., 11:46:43

    А почему у меня выкидывает Fatal?

    Fatal error: Call to undefined method PrivacyViolator::caller() in /in/ntf08 on line 15 3v4l.org/ntf08

  9. №9851
    klay
    klay 28 июня 2015 г., 14:39:23

    @romanitalian Ну, всегда можно попробовать рефлексию ;)

    3v4l.org/qOcSR

  10. №9860
    romanitalian
    romanitalian 02 июля 2015 г., 15:13:21

    @klay Спасибо.

    Позволил собрать несколько вариантов у себя в блоге: romanitalian.github.io.local/sections/php/use_private/index.html

  11. №9862
    klay
    klay 02 июля 2015 г., 17:23:39

    @romanitalian 404

  12. №9879
    romanitalian
    romanitalian 06 июля 2015 г., 16:49:21

    @klay надо переезжать с jino.ru (периодически отваливается хостинг)

  13. №9881
    romanitalian
    romanitalian 06 июля 2015 г., 21:35:25

    @klay не туда написал - про jino :(

  14. №9939
    Shkarbatov
    Shkarbatov 22 авг. 2015 г., 16:21:53

    А действительно в чем дело? 3v4l.org/S5j87

    Fatal error: Call to undefined method PrivacyViolator::_caller()

  15. №9940
    Shkarbatov
    Shkarbatov 22 авг. 2015 г., 19:15:13

    Вот так вот получилось: 3v4l.org/50bnu

    Fatal error: Call to undefined method PrivacyViolator::_caller()

    В примере из заметки

    $this->caller->bindTo($object, $object);
    return $this->caller($method, $args);

    Между собой получаются не связанные, то есть надо либо связать переменной, либо вызвать в цепочке:

    return $this->caller->bindTo($object, $object)->__invoke($method, $args);

    Александр, а Вас работает пример из заметки?

  16. №9942
    Sam
    Sam 23 авг. 2015 г., 20:39:38

    Shkarbatov, да, вызов метода был неверно сделан. Поправил. В реальном коде оно не было завёрнуто в класс...

    Спасибо!

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

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

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