在PHP中从类外部调用受保护的方法

在PHP中从类外部调用受保护的方法,php,access-modifiers,Php,Access Modifiers,我有一个非常特殊的情况,我需要从类外部调用一个受保护的方法。我非常清楚我在编程方面做了什么,但我不会完全反对在这个特殊情况下这样做。在所有其他情况下,我需要继续禁止对内部方法的访问,因此我希望保护该方法 在类之外访问受保护的方法有哪些优雅的方法?到目前为止,我已经找到了 我想可能会创建某种目标类的双代理实例,偷偷地提供对内部的访问…我只是把它扔出去,因为我已经两年没有用PHP编程了。您能像这样向调用受保护方法的类添加一个函数吗 $obj->publicFunc = create_funct

我有一个非常特殊的情况,我需要从类外部调用一个受保护的方法。我非常清楚我在编程方面做了什么,但我不会完全反对在这个特殊情况下这样做。在所有其他情况下,我需要继续禁止对内部方法的访问,因此我希望保护该方法

在类之外访问受保护的方法有哪些优雅的方法?到目前为止,我已经找到了


我想可能会创建某种目标类的双代理实例,偷偷地提供对内部的访问…

我只是把它扔出去,因为我已经两年没有用PHP编程了。您能像这样向调用受保护方法的类添加一个函数吗

$obj->publicFunc = create_function('$arg', 'return $this->protectedFunc($arg);');
编辑我认为Tom查看create_函数的文档是正确的。当您尝试使用此示例调用$this时,它的范围似乎是“错误的”。


PHP 5.3.0也支持传统的匿名函数(我的第一个解决方案可能不起作用),所以我可能会这样写:

$obj->publicFunc = function($arg) { 
     return $this->protectedFunc($arg); 
};
因为我认为它看起来更干净(当然,您选择的IDE会更好地突出显示它)


呃,我尝试使用调用该方法,但PHP也不允许您这样做。看来你得像其他海报建议的那样,使用某种儿童课程。如果您找到了一个有效的方法,开发人员可能会在将来将其归类为bug,并在您升级到下一个版本时破坏您的代码


我建议扩展该类。

这有点麻烦,但可能是一种选择

添加子类以访问受保护的函数

public class Child extends Parent {
    public function protectedFunc() {
        return parent::protectedFunc();
    }
}

然后,实例化一个需要调用该函数的
Child
实例,而不是
Parent

我认为,在这种情况下,重构使您不需要这种东西可能是最优雅的方法。其中一个选项是使用
\u call
并在该parse
debug\u backtrace
中查看哪个类调用了该方法。然后检查一个朋友whitelst

class ProtectedClass {

    // Friend list
    private $friends = array('secret' => array('FriendClass')); 

    protected function secret($arg1, $arg2) {
        // ...
    }

    public function __call($method, $args) {

        $trace = debug_backtrace();
        $class = $trace[1]['class'];
        if(in_array($class, $this->friends[$method]))
            return $this->$method($args[0], $args[1]);

        throw new Exception();
    }
}

我想我需要一个淋浴。

如果我必须调用一个私有函数,我会考虑程序设计的问题

过去的情况是

  • 你的班级负责几件事(实际上是两个或两个以上的卷轴)或者
  • 封装规则被打破(例如,实用程序函数)

通过找到绕过这些问题的任何方法,您将无法接近真正的解决方案。

假设您的方法声明如下:

protected function getTheFoo() {
    ...
}

protected function setTheFoo($val) {
    ...
}
用法:

$obj->__get('the_foo');
$obj->__set('the_foo', 'myBar');

这绕过了受保护的方法,直接转到实例变量。

在PHP中,可以使用反射来实现这一点。 要调用受保护或私有方法,请使用setAccessible()方法
(只需将其设置为TRUE)

不,这是一个很好的选择。我可能会试一试。如果有效,我会告诉你的。我想这将创建一个字符串$obj->publicFunc,这是新函数的名称。当您尝试调用它时,它的作用域与普通函数的作用域相同。我无法让它正常工作:。我得到的错误是“调用未定义的方法Chad::publicFunction()”。我可能做错了什么?反射是个好主意,在5.3中,您可以使用setAccessible()来调用受保护的方法method@DaveL,您可以在方法上执行此操作,方法是使用ReflectionMethod而不是ReflectionProperty。嗯,是的,这看起来是我目前唯一的选择。也许我应该称这个班为间谍o_o。最好的方法是什么?将函数更改为public。一般来说,这是一个很好的建议。但有时在方法定义的范围之外调用方法是有充分理由的。例如,如果您不想使方法成为API的一部分,但希望在测试中调用它。或者在CodeIgniter视图中,您可能希望您的密码哈希函数不可从web调用,但您确实希望在测试中调用它们。与C++不同,PHP没有“特权”类,它可以访问类内部结构。如果使用的是不暴露该方法的第三方API,但确实需要访问该方法。Csaba提出的观点肯定是正确的,但在极少数情况下,你可能不得不违反规则。你应该告诉自己如何做,作为答案,而不是将其他答案(在本例中,是文档)链接起来。不过,我们鼓励您链接到您的源代码和其他重要文档。为什么不直接使用反射呢?