是否可以覆盖PHP中的函数

时间:2010-09-01 17:34:14

标签: php function redeclaration

你可以声明这样的函数......

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

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

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

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

任何方式?

10 个答案:

答案 0 :(得分:91)

修改

  

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

有一个名为override_function的功能,实际上符合要求。但是,鉴于此函数是The Advanced PHP Debugger扩展的一部分,因此很难创建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();

答案 1 :(得分:58)

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

比修改解释器更少回避的方法是猴子补丁。

Monkey修补是用你自己的类似“补丁”替换实际实现的艺术。

忍者技能

在你像PHP忍者一样修补补丁之前,我们首先要了解PHP的命名空间。

从PHP 5.3开始,我们引入了名称空间,你可能乍一看这些名称空间可能与java包相似,但它并不完全相同。 PHP中的命名空间是一种通过创建焦点层次结构来封装范围的方法,尤其是对于函数和常量。正如本主题fallback to global functions,旨在解释。

如果在调用函数时不提供命名空间,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) {},因为这会导致名称冲突,因为具有该名称的函数已经存在。

预计会出现致命错误:

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();

适用于模拟单元测试。

的nJoy!

答案 2 :(得分:25)

查看override_function以覆盖这些功能。

  

override_function - 覆盖内置函数   功能

示例:

override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');

答案 3 :(得分:13)

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

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

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

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

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

答案 4 :(得分:11)

您无法在PHP中重新声明任何函数。但是,您可以覆盖它们。查看overriding functions以及renaming functions,以便根据需要保存您要覆盖的功能。

因此,请记住,当您覆盖某个函数时,会丢失它。您可能需要考虑保留它,但使用其他名称。只是说。

此外,如果这些是你想要覆盖的类中的函数,你只需要创建一个子类并重新声明你的类中的函数,而不必执行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 :(得分:4)

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

例如simple.inc将包含function boofoo() { simple },而really.inc将包含function boofoo() { really }

它有助于您的程序的可读性/维护性,同一类inc具有相同类型的所有功能。

然后在主模块的顶部

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

答案 6 :(得分:3)

您可以使用PECL扩展程序

但在我看来这是不好的做法。您正在使用功能,但请查看Decorator design pattern。可以从中借用基本思想。

答案 7 :(得分:1)

不,这不是问题。 PHP Variable Functions

答案 8 :(得分: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()”。

答案 9 :(得分:0)

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

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

$greet('World');

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