Блог веб-разработчика v 1.0.0
Symfony2, AngularJS, React, Gulp, PhpStorm и много других страшных слов

Переопределение private и protected методов в PHP

10 лет назад
10492 просмотра
PHP Полезности

Patchwork - библиотека на чистом PHP, своеобразная обертка над runkit_function_redefine, но с более удобным интерфейсом.

Для работы потребуется PHP 5.3+ или HHVM 3.2. Хотя разработчик говорит, что работать может и на более ранних версиях HHVM. А вот на PHP ниже 5.3 не запустится из-за отсутствия лямбда-функций.

Помимо простых функций можно переопределять методы классов, в том числе статические, финальные (final) и даже непубличные (private, protected). Исходя из этого применений библиотеке можно найти достаточно много, если вас, например, не устраивает работа закрытых методов какой-то библиотеки.

Установка

Удобнее всего устанавливать через Composer, добавив зависимость:

{
     "require-dev": {
         "antecedent/patchwork": "*"
     }
}

Переопределение пользовательских функций

Предположим, у нас есть функция test(), например такая:

function test() {
    echo 'Original';
}

Мы можем запросто ее переопределить вот так:

$handle = Patchwork\replace("test", function() {
    return "Override";
});

test(); # => "Override"

Чтобы отменить наше переопределение нужно вызвать:

Patchwork\undoAll(); # Отменит всё
Patchwork\undo($handle); # Отменит только указанный оверрайд

Переопределение методов

Переопределение методов ничем не отличается от функций:

Patchwork\replace('YourClass\method', function($key) {
    echo "Переопределено";

    # А вот так можно вызвать оригинальную функцию. Что-то вроде parent:: в классе
    Patchwork\pass();

    # Можно обращаться напрямую к $this, но только в PHP5.4+
    $someVar = $this->id;

    # Для более ранних версий нужно использовать такой способ
    $someVar = Patchwork\Stack\top('object')->id;
});

Обратите внимание, что у вас нет доступа к self, parent и static, а так же к get_called_class внутри переопределенного метода. Чтобы до них достучаться нужно использовать полное наименование класса вместо self и parent, а get_called_class и static можно заменить на Patchwork\Stack\topCalledClass().

Чуть более подробная документация доступна по ссылке: http://antecedent.github.io/patchwork/docs/usage.html

А так же репозиторий на GitHub: https://github.com/antecedent/patchwork

Что еще почитать