是否可以在 PHP 中覆盖函数命名空间 php 中的猴子补丁 >= 5.3

2022-08-30 08:21:50

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

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

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

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

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

无论如何?


答案 1

编辑

要解决此答案未直接解决原始问题的评论。如果您从谷歌搜索来到这里,请从这里开始

有一个名为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();

答案 2

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

与修改解释器相比,一种不那么回避的方法是猴子补丁。

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

忍者技能

在你像PHP Ninja一样猴子补丁之前,我们首先必须了解PHP命名空间。

从 PHP 5.3 开始,我们引入了命名空间,乍一看你可能会认为它们等同于 java 包之类的东西,但它并不完全相同。在 PHP 中,命名空间是一种通过创建焦点层次结构来封装范围的方法,特别是对于函数和常量。正如本主题所述,回退到全局函数,旨在解释。

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

您将无法在全局命名空间中定义 a,因为这将导致名称冲突,因为具有该名称的函数已存在。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();

非常适合模拟单元测试。

哎呀!


推荐