78

你能声明一个这样的函数吗...

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

然后重新声明它有点像这样......

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

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

反正?

4

10 回答 10

110

编辑

为了解决这个答案没有直接解决原始问题的评论。如果您是通过 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();
于 2010-09-01T17:46:01.673 回答
84

命名空间 php >= 5.3 中的猴子补丁

猴子补丁是比修改解释器更隐蔽的方法。

猴子补丁是用您自己的类似“补丁”替换实际实现的艺术。

忍者技能

在你可以像 PHP Ninja 一样修改补丁之前,我们首先必须了解 PHP 的命名空间。

自 PHP 5.3 起,我们开始介绍命名空间,乍一看,它们可能等同于 java 包之类的东西,但并不完全相同。在 PHP 中,命名空间是一种通过创建焦点层次来封装范围的方法,尤其是对于函数和常量。作为本主题,回退到全局函数,旨在解释。

如果在调用函数时没有提供命名空间,PHP 会首先在当前命名空间中查找,然后向下移动层次结构,直到找到在该前缀命名空间中声明的第一个函数并执行该函数。对于我们的示例,如果您print_r();从调用namespace My\Awesome\Namespace;PHP 所做的是首先查找调用的函数,然后My\Awesome\Namespace\print_r();直到它在全局命名空间中找到 PHP 内置函数。My\Awesome\print_r();My\print_r();\print_r();

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

预计会出现以下致命错误:

Fatal error: Cannot redeclare print_r()

但是,没有什么能阻止您在命名空间范围内这样做。

给猴子打补丁

假设您有一个使用多个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);

但是您后来改变了主意,您希望将输出包装在<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);
    }

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

非常适合模拟单元测试。

开心!

于 2012-08-26T06:13:24.353 回答
25

看看override_function重写函数。

override_function — 覆盖内置函数

例子:

override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');
于 2010-09-01T17:36:33.487 回答
14

简短的回答是否定的,一旦函数在 PHP 函数范围内,你就不能覆盖它。

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

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

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

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

于 2010-09-01T17:37:07.993 回答
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;');
于 2010-09-01T17:41:46.250 回答
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";
  }
于 2010-09-01T17:41:22.527 回答
3

您可以使用 PECL 扩展

但在我看来,这是不好的做法。您正在使用函数,但请查看装饰器设计模式。可以借用它的基本思想。

于 2010-09-01T17:40:54.507 回答
1

不,这将是一个问题。 PHP 变量函数

于 2010-09-01T17:36:08.167 回答
1

针对您拥有可以编辑的包含文件 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";}
?>

浏览到主文件显示“这是 B 中的 F1() ”。

于 2018-10-22T15:49:20.810 回答
1

根据您需要的情况,也许您可​​以使用这样的匿名函数:

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

$greet('World');

...然后您可以随时为给定变量设置新函数

于 2017-09-02T03:02:13.293 回答