Можно ли переписать функцию в PHP? - PullRequest
60 голосов
/ 01 сентября 2010

Можете ли вы объявить функцию, подобную этой ...

function ihatefooexamples(){
  return "boo-foo!";
};

А потом переопределить это примерно так ...

if ($_GET['foolevel'] == 10){
  function ihatefooexamples(){
    return "really boo-foo";
  };
};

Можно ли переписать функцию таким образом?

В любом случае?

Ответы [ 10 ]

91 голосов
/ 01 сентября 2010

Редактировать

Чтобы ответить на комментарии, этот ответ не имеет прямого отношения к исходному вопросу.Если вы попали сюда из Поиска Google, начните здесь

Доступна функция под названием override_function , которая действительно соответствует требованиям.Однако, учитывая, что эта функция входит в расширение Advanced PHP Debugger , трудно привести аргумент, что override_function() предназначен для производственного использования.Поэтому, я бы сказал «Нет», невозможно переписать функцию с намерением, которое имел в виду первоначальный спрашивающий.

Оригинальный ответ

Здесь вы должны воспользоватьсяООП, а именно полиморфизм.

interface Fooable
{
    public function ihatefooexamples();
}

class Foo implements Fooable
{
    public function ihatefooexamples()
    {
        return "boo-foo!";
    }
}

class FooBar implements Fooable
{
    public function ihatefooexamples()
    {
        return "really boo-foo";
    }
}

$foo = new Foo();

if (10 == $_GET['foolevel']) {
    $foo = new FooBar();
}

echo $foo->ihatefooexamples();
59 голосов
/ 26 августа 2012

Патч Monkey в пространстве имен php> = 5.3

Менее уклончивый метод, чем модификация интерпретатора, - это обезьянья заплатка.

Исправление обезьяны - это искусство замены реальной реализации аналогичным «собственным» патчем.

Навыки ниндзя

Прежде чем вы сможете сделать патч для обезьяны, как ниндзя PHP, мы сначала должны понять пространства имен PHP.

Начиная с PHP 5.3 мы познакомились с пространствами имен, которые вы, на первый взгляд, могли бы обозначить как нечто эквивалентное java-пакетам, но это не совсем то же самое. Пространства имен в PHP - это способ инкапсулировать область видимости, создавая иерархию фокуса, особенно для функций и констант. Как объясняется в этом разделе, отступление от глобальных функций .

Если вы не предоставляете пространство имен при вызове функции , PHP сначала просматривает текущее пространство имен, затем перемещается вниз по иерархии, пока не найдет первую функцию, объявленную в этом префиксном пространстве имен, и не выполнит ее. Например, если вы вызываете print_r(); из namespace My\Awesome\Namespace;, PHP сначала ищет функцию с именем My\Awesome\Namespace\print_r();, затем My\Awesome\print_r();, а затем My\print_r();, пока не найдет встроенную функцию PHP в глобальном пространстве имен * 1022. *.

Вы не сможете определить function print_r($object) {} в глобальном пространстве имен, потому что это вызовет конфликт имен, так как функция с таким именем уже существует.

Ожидайте фатальную ошибку, например:

Fatal error: Cannot redeclare print_r()

Но ничто не мешает вам делать это в рамках пространства имен.

Исправление обезьяны

Допустим, у вас есть скрипт, использующий несколько print_r(); вызовов.

* +1037 * Пример:
<?php
     print_r($some_object);
     // do some stuff
     print_r($another_object);
     // do some other stuff
     print_r($data_object);
     // do more stuff
     print_r($debug_object);

Но позже вы передумаете, и вместо этого вы захотите заключить вывод в теги . С тобой когда-нибудь случалось?

Перед тем как перейти и изменить каждый вызов на print_r();, рассмотрите вместо этого патчи для обезьян.

Пример: * 1 047 * <code><?php namespace MyNamespace { function print_r($object) { echo "<pre>", \print_r($object, true), " "; } print_r ($ some_object); // делать что-то print_r ($ another_object); // делать другие вещи print_r ($ data_object); // делать больше вещей print_r ($ debug_object); } Ваш скрипт теперь будет использовать MyNamespace\print_r(); вместо глобального \print_r(); Прекрасно подходит для юнит-тестов. NJoy!

25 голосов
/ 01 сентября 2010

Посмотрите на override_function для переопределения функций.

override_function - Переопределяет встроенные функции

Пример:

override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');
13 голосов
/ 01 сентября 2010

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

ваш лучший способ использования анонимных функций, таких как

$ihatefooexamples = function()
{
  return "boo-foo!";
}

//...
unset($ihatefooexamples);
$ihatefooexamples = function()
{
   return "really boo-foo";
}

http://php.net/manual/en/functions.anonymous.php

11 голосов
/ 01 сентября 2010

Вы не можете переопределить какие-либо функции в PHP. Вы можете, однако, переопределить их. Проверьте переопределяющие функции , а также переименовывающие функции , чтобы сохранить переопределяемую функцию, если хотите.

Итак, имейте в виду, что при переопределении функции вы теряете ее. Возможно, вы захотите сохранить его, но под другим именем. Просто говорю.

Кроме того, если это функции в классах, которые вы хотите переопределить, вам просто нужно создать подкласс и повторно объявить функцию в вашем классе, не выполняя rename_function и override_function.

Пример:

rename_function('mysql_connect', 'original_mysql_connect' );
override_function('mysql_connect', '$a,$b', 'echo "DOING MY FUNCTION INSTEAD"; return $a * $b;');
5 голосов
/ 01 сентября 2010

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

Например, simple.inc будет содержать function boofoo() { simple }, а really.inc будет содержать function boofoo() { really }

Это помогает удобочитаемости / поддержке вашей программы, имея все функции одного и того же вида в одном и том же inc.

Тогда наверху вашего основного модуля

  if ($_GET['foolevel'] == 10) {
    include "really.inc";
  }
  else {
    include "simple.inc";
  }
3 голосов
/ 01 сентября 2010

Вы можете использовать расширение PECL

но это плохая практика, по моему мнению. Вы используете функции, но посмотрите шаблон проектирования Decorator . Может позаимствовать у него основную идею.

1 голос
/ 22 октября 2018

Решение для связанного случая, когда у вас есть включаемый файл A, который вы можете редактировать и хотите переопределить некоторые из его функций во включаемом файле B (или в основном файле):

Основной файл:

<?php
$Override=true; // An argument used in A.php
include ("A.php");
include ("B.php");
F1();
?>

Включить файл A:

<?php
if (!@$Override) {
   function F1 () {echo "This is F1() in A";}
}
?>

Включить файл B:

<?php
   function F1 () {echo "This is F1() in B";}
?>

При просмотре основного файла отображается « Это F1 () вB ».

1 голос
/ 01 сентября 2010

Нет, это будет проблемой. Функции переменных PHP

0 голосов
/ 02 сентября 2017

В зависимости от ситуации, где это необходимо, может быть, вы можете использовать анонимные функции, такие как:

$greet = function($name)
{
    echo('Hello ' . $name);
};

$greet('World');

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...