Можно ли заменить (monkeypatch) функции PHP? - PullRequest
17 голосов
/ 10 февраля 2009

Вы можете сделать это в Python, но возможно ли это в PHP?

>>> def a(): print 1
... 
>>> def a(): print 2
... 
>>> a()
2

например:.

<? function var_dump() {} ?>
Fatal error: Cannot redeclare var_dump() in /tmp/- on line 1

Ответы [ 6 ]

13 голосов
/ 08 августа 2013

Это бит поздно, но я просто хочу отметить, что начиная с PHP 5.3, на самом деле можно переопределять внутренние функции без использования расширения PHP.

Хитрость в том, что вы можете переопределить внутреннюю функцию PHP внутри пространства имен. Он основан на том, как PHP выполняет разрешение имен для функций:

Внутри пространства имен (скажем, A \ B) вызовы неквалифицированных функций разрешаются во время выполнения. Вот как разрешается вызов функции foo ():

  1. Ищет функцию из текущего пространства имен: A \ B \ foo ().
  2. Он пытается найти и вызвать глобальную функцию foo ()
9 голосов
/ 10 февраля 2009

Нет, это невозможно сделать так, как вы могли бы ожидать.

Из manual:

PHP не поддерживает перегрузку функций, а также невозможно отменить или переопределить ранее объявленные функции.

ОДНАКО, вы можете использовать runkit_function_redefine и его кузенов, но это определенно не очень элегантно ...

Вы также можете использовать create_function, чтобы сделать что-то вроде этого:

<?php
$func = create_function('$a,$b','return $a + $b;');
echo $func(3,5); // 8
$func = create_function('$a,$b','return $a * $b;');
echo $func(3,5); // 15
?>

Как и в случае с runkit, он не очень элегантен, но дает поведение, которое вы ищете.

5 голосов
/ 02 ноября 2010

Я понимаю, что этот вопрос немного устарел, но Patchwork - это недавно выпущенный проект PHP 5.3, который поддерживает переопределение пользовательских функций. Хотя, как упоминает автор, вам придется прибегнуть к runkit или php-test-helpers к функциям ядра / библиотеки monkey-patch.

2 голосов
/ 10 февраля 2009
1 голос
/ 27 апреля 2012

Как упоминал jmikola, Patchwork - хорошее решение, если вы хотите добавить код в функцию.

Вот статья о том, как это работает: http://phpmyweb.net/2012/04/26/write-an-awesome-plugin-system-in-php/

Поставляется с некоторым примером кода. Я думаю, что версия phpmyweb использует немного лучший код, потому что он не использует код eval (), в отличие от пэчворка. Вы можете кэшировать коды операций при использовании eval ().

0 голосов
/ 17 ноября 2016

принятый ответ превосходен !!! Я просто добавлю, что вы можете поместить свои коды в скобки пространства имен , и тогда значение по умолчанию GLOBAL-SPACE сбрасывается.

некоторые другие способы:

1) функция переименования ($ old_name, $ new_name)

2) override_function ($ old_name, $ parameters, $ new_func)

и редко используется:

3) runkit_function_rename (...)

4) runkit_function_redefine (...)

...