是否可以覆盖PHP中的函数

Mar*_*lor 64 php function redeclaration

你能宣布一个这样的函数......

function ihatefooexamples(){
  return "boo-foo!";
};
Run Code Online (Sandbox Code Playgroud)

然后重新宣布它有点像这样......

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

是否有可能以这种方式覆盖一个函数?

无论如何?

Pet*_*ley 95

编辑

为了解决这些答案没有直接解决原始问题的评论.如果您从Google搜索到达此处,请从此处开始

有一个名为override_function的函数实际上适合账单.但是,鉴于此函数是高级PHP调试器扩展的一部分,很难创建一个override_function()供生产使用的参数.因此,我会说"不",不可能以原始提问者的想法覆盖一个函数.

原始答案

这是你应该利用OOP,特别是多态性的地方.

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();
Run Code Online (Sandbox Code Playgroud)

  • +1解决实际问题,而不是简单地试图回答确切的问题...... (15认同)
  • 我不同意,有了这个答案,问题清楚地说"功能",而不是"方法",很明显上下文不是一个类.我是从Google搜索来到这里的,目前我正在使用非OO遗留库,这个答案毫无用处. (6认同)
  • @mastazi感谢您向我指出这是谷歌搜索此问题的最佳答案.我已经更新了答案,其中的信息可以帮助未来的答案寻求者与您自己的目标相似. (3认同)
  • 我要做的唯一改变是将`$ foo = new Foo()`放在`else`块中,以防构造函数(a)价格昂贵,或者(b)有副作用. (2认同)
  • @Gordon你过度分析了.我认为很明显这只是一个例子. (2认同)
  • 不回答问题。我正在使用声明了全局函数的框架。我不想要它们,并且想更换它们。有了这个答案,这是完全没有用的。 (2认同)

nic*_*kl- 63

名称空间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 \print_r();.

您将无法function print_r($object) {}在全局命名空间中定义a ,因为这将导致名称冲突,因为具有该名称的函数已存在.

预计会出现致命错误:

Fatal error: Cannot redeclare print_r()
Run Code Online (Sandbox Code Playgroud)

但是,没有什么能阻止你在命名空间范围内做这件事.

修补猴子

假设您有一个使用多个print_r();调用的脚本.

例:

<?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);
Run Code Online (Sandbox Code Playgroud)

但是你以后会改变主意,而你希望输出包含在<pre></pre>标签中.曾经发生在你身上?

在你去之前改变每个电话来print_r();考虑猴子修补.

例:

<?php
    namespace MyNamespace {
        function print_r($object) 
        {
            echo "<pre>", \print_r($object, true), "</pre>"; 
        }

        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);
    }
Run Code Online (Sandbox Code Playgroud)

您的脚本现在将使用MyNamespace\print_r();而不是全局\print_r();

适用于模拟单元测试.

的nJoy!

  • 一个非常有价值的方法!感谢分享 (4认同)
  • 当函数 A、B 和 C 在现有的大型包含文件中定义时(我不想更改这些,因为其他页面使用它们)并且我只想覆盖主函数中的函数 B,我无法使此工作文件,其中 B 在单独的包含文件中定义。我猜命名空间在这种情况下不起作用。 (2认同)

Sar*_*raz 25

看看override_function要覆盖这些功能.

override_function - 覆盖内置函数

例:

override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');
Run Code Online (Sandbox Code Playgroud)

  • 这是一个好点,但如果函数很大,那么传递字符串就不好了!:(,另一点是,这只能用于内置函数而不是用户定义! (2认同)
  • 我尝试使用覆盖功能,但它是 PECL 的一部分,并且需要首先配置 PECL。 (2认同)

Rob*_*itt 13

简短的回答是否定的,你不能在PHP函数范围内覆盖一个函数.

你最好使用这样的匿名函数

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

//...
unset($ihatefooexamples);
$ihatefooexamples = function()
{
   return "really boo-foo";
}
Run Code Online (Sandbox Code Playgroud)

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

  • @ircmax你不必使用`unset` (2认同)

小智 11

您无法在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;');
Run Code Online (Sandbox Code Playgroud)

  • 这需要APD PECL扩展,并且已经过时.最新版本是2004年.http://pecl.php.net/package/apd (14认同)

Rin*_*g Ø 5

我会在一个include文件中包含一个案例的所有功能,而在另一个文件中包含其他功能include

例如simple.inc将包含function boofoo() { simple }并且really.inc将包含function boofoo() { really }

它具有相同种类的所有功能,有助于提高程序的可读性/维护性inc

然后在主模块的顶部

  if ($_GET['foolevel'] == 10) {
    include "really.inc";
  }
  else {
    include "simple.inc";
  }
Run Code Online (Sandbox Code Playgroud)