是否可以在 PHP 中覆盖函数命名空间 php 中的猴子补丁 >= 5.3
你能声明一个这样的函数吗?
function ihatefooexamples(){
return "boo-foo!";
};
然后像这样重新声明它...
if ($_GET['foolevel'] == 10){
function ihatefooexamples(){
return "really boo-foo";
};
};
是否可以以这种方式覆盖函数?
无论如何?
你能声明一个这样的函数吗?
function ihatefooexamples(){
return "boo-foo!";
};
然后像这样重新声明它...
if ($_GET['foolevel'] == 10){
function ihatefooexamples(){
return "really boo-foo";
};
};
是否可以以这种方式覆盖函数?
无论如何?
要解决此答案未直接解决原始问题的评论。如果您从谷歌搜索来到这里,请从这里开始
有一个名为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();
与修改解释器相比,一种不那么回避的方法是猴子补丁。
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();
非常适合模拟单元测试。
哎呀!