简体   繁体   English

是否可以覆盖PHP中的函数

[英]Is it possible to overwrite a function in PHP

Can you declare a function like this... 你能宣布一个这样的函数......

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

And then redeclare it somewhat like this... 然后重新宣布它有点像这样......

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

Is it possible to overwrite a function that way? 是否有可能以这种方式覆盖一个函数?

Any way? 无论如何?

Edit 编辑

To address comments that this answer doesn't directly address the original question. 为了解决这些答案没有直接解决原始问题的评论。 If you got here from a Google Search, start here 如果您从Google搜索到达此处,请从此处开始

There is a function available called override_function that actually fits the bill. 有一个名为override_function的函数实际上适合账单。 However, given that this function is part of The Advanced PHP Debugger extension, it's hard to make an argument that override_function() is intended for production use. 但是,鉴于此函数是高级PHP调试器扩展的一部分,因此很难创建override_function()用于生产用途的参数。 Therefore, I would say "No", it is not possible to overwrite a function with the intent that the original questioner had in mind. 因此,我会说“不”,不可能以原始提问者的想法覆盖一个函数。

Original Answer 原始答案

This is where you should take advantage of OOP, specifically polymorphism. 这是你应该利用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();

Monkey patch in namespace php >= 5.3 名称空间php> = 5.3中的猴子补丁

A less evasive method than modifying the interpreter is the monkey patch. 比修改解释器更少回避的方法是猴子补丁。

Monkey patching is the art of replacing the actual implementation with a similar "patch" of your own. 猴子修补是用你自己的类似“补丁”取代实际实现的艺术。

Ninja skills 忍者技能

Before you can monkey patch like a PHP Ninja we first have to understand PHPs namespaces. 在你像PHP忍者一样修补补丁之前,我们首先要了解PHP的命名空间。

Since PHP 5.3 we got introduced to namespaces which you might at first glance denote to be equivalent to something like java packages perhaps, but it's not quite the same. 从PHP 5.3开始,我们引入了名称空间,你可能乍一看它们可能等同于java包这样的东西,但它们并不完全相同。 Namespaces, in PHP, is a way to encapsulate scope by creating a hierarchy of focus, especially for functions and constants. PHP中的命名空间是一种通过创建焦点层次结构来封装范围的方法,尤其是对于函数和常量。 As this topic, fallback to global functions , aims to explain. 作为这个话题, 回归全球功能 ,旨在解释。

If you don't provide a namespace when calling a function , PHP first looks in the current namespace then moves down the hierarchy until it finds the first function declared within that prefixed namespace and executes that. 如果在调用函数时没有提供命名空间 ,PHP首先查找当前命名空间,然后向下移动层次结构,直到找到在该前缀命名空间内声明的第一个函数并执行该命名空间。 For our example if you are calling print_r(); 对于我们的示例,如果您正在调用print_r(); from namespace My\\Awesome\\Namespace; 来自namespace My\\Awesome\\Namespace; What PHP does is to first look for a function called My\\Awesome\\Namespace\\print_r(); PHP的作用是首先查找名为My\\Awesome\\Namespace\\print_r();的函数My\\Awesome\\Namespace\\print_r(); then My\\Awesome\\print_r(); 然后My\\Awesome\\print_r(); then My\\print_r(); 然后My\\print_r(); until it finds the PHP built in function in the global namespace \\print_r(); 直到它在全局命名空间\\print_r();找到PHP内置函数\\print_r(); .

You will not be able to define a function print_r($object) {} in the global namespace because this will cause a name collision since a function with that name already exists. 您将无法在全局命名空间中定义function print_r($object) {} ,因为这将导致名称冲突,因为具有该名称的函数已存在。

Expect a fatal error to the likes of: 预计会出现致命错误:

Fatal error: Cannot redeclare print_r()

But nothing stops you, however, from doing just that within the scope of a namespace. 但是,没有什么能阻止你在命名空间范围内做这件事。

Patching the monkey 修补猴子

Say you have a script using several print_r(); 假设你有一个使用几个print_r();的脚本print_r(); calls. 调用。

Example: 例:

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

But you later change your mind and you want the output wrapped in <pre></pre> tags instead. 但是你后来改变了主意,希望输出包含在<pre></pre>标签中。 Ever happened to you? 曾经发生在你身上?

Before you go and change every call to print_r(); 在你去之前改变每次调用print_r(); consider monkey patching instead. 考虑猴子修补。

Example: 例:

<?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);
    }

Your script will now be using MyNamespace\\print_r(); 您的脚本现在将使用MyNamespace\\print_r(); instead of the global \\print_r(); 而不是全局\\print_r();

Works great for mocking unit tests. 适用于模拟单元测试。

nJoy! 的nJoy!

Have a look at override_function to override the functions. 看看override_function来覆盖这些函数。

override_function — Overrides built-in functions override_function - 覆盖内置函数

Example: 例:

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

short answer is no, you can't overwrite a function once its in the PHP function scope. 简短的回答是否定的,你不能在PHP函数范围内覆盖一个函数。

your best of using anonymous functions like so 你最好使用这样的匿名函数

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

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

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

You cannot redeclare any functions in PHP. 您无法在PHP中重新声明任何函数。 You can, however, override them. 但是,您可以覆盖它们。 Check out overriding functions as well as renaming functions in order to save the function you're overriding if you want. 查看覆盖功能以及重命名功能 ,以便在需要时保存您要覆盖的功能。

So, keep in mind that when you override a function, you lose it. 所以,请记住,当你覆盖一个函数时,你会失去它。 You may want to consider keeping it, but in a different name. 您可能需要考虑保留它,但使用其他名称。 Just saying. 只是说。

Also, if these are functions in classes that you're wanting to override, you would just need to create a subclass and redeclare the function in your class without having to do rename_function and override_function. 此外,如果这些是您想要覆盖的类中的函数,则只需创建一个子类并重新声明类中的函数,而无需执行rename_function和override_function。

Example: 例:

rename_function('mysql_connect', 'original_mysql_connect' );
override_function('mysql_connect', '$a,$b', 'echo "DOING MY FUNCTION INSTEAD"; return $a * $b;');

I would include all functions of one case in an include file, and the others in another include . 我将一个案例的所有功能都包含在一个include文件中,而另一个include在另一个案例中。

For instance simple.inc would contain function boofoo() { simple } and really.inc would contain function boofoo() { really } 例如, simple.inc将包含function boofoo() { simple }really.inc将包含function boofoo() { really }

It helps the readability / maintenance of your program, having all functions of the same kind in the same inc . 它有助于程序的可读性/维护,在同一个inc具有相同类型的所有功能。

Then at the top of your main module 然后在主模块的顶部

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

You could use the PECL extension 您可以使用PECL扩展

but that is bad practise in my opinion. 但在我看来这是不好的做法。 You are using functions, but check out the Decorator design pattern . 您正在使用函数,但请查看Decorator设计模式 Can borrow the basic idea from it. 可以借用它的基本思想。

No this will be a problem. 不,这将是一个问题。 PHP Variable Functions PHP变量函数

A solution for the related case where you have an include file A that you can edit and want to override some of its functions in an include file B (or the main file): 对于相关案例的解决方案,您有一个包含文件A,您可以编辑并希望覆盖包含文件B(或主文件)中的某些功能:

Main File: 主文件:

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

Include File A: 包含文件A:

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

Include File B: 包括文件B:

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

Browsing to the main file displays " This is F1() in B ". 浏览到主文件显示“ 这是B中的F1() ”。

Depending on situation where you need this, maybe you can use anonymous functions like this: 根据您需要的情况,也许你可以使用这样的匿名函数:

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

$greet('World');

...then you can set new function to the given variable any time ...然后您可以随时为给定变量设置新功能

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM