静态方法可以访问调用者对象,bug还是功能?

时间:2010-09-12 17:02:08

标签: php oop object methods static

我正在处理我的应用程序并发现了静态调用但未定义为扩展同一类的静态方法的奇怪行为。最终,此方法可以访问和更改调用者保护的变量和方法。 以下是我的代码示例:

<?php

class object
{
    private $version;

    protected $alteredBy = 'nobody';

    public function __construct()
    {
        $this->version    = PHP_VERSION;

        $this->objectName = get_class($this);

        echo sprintf("<pre><strong>New %s Created</strong>", $this->objectName);

    }

    public function __destruct()
    {
        echo sprintf("</pre><strong>Source Code</strong><div>%s</div>", highlight_file(__FILE__, true));
    }
}

class superApplication extends object
{
    public function __toString()
    {
        echo "\nCalling third party object statically like thirdParty::method()\n";

        echo thirdParty::method();

        echo "\nCalling third party object statically via call_user_func()\n";

        echo call_user_func(array('thirdParty','method'));

        echo sprintf("New Object params\n%s", print_r($this, true));

        return sprintf("%s: done\n", $this->objectName);
    }
}

class thirdParty extends object
{    
    public function method()
    {
        if(is_object($this))
        {
            $this->alteredBy = __CLASS__;

            return sprintf(
                "<span style=\"color:red\">Object '%s' was altered successfully by %s class</span>\n", 
                get_class($this),
                __CLASS__
            );
        }
        else return "Cannot access caller object\n\n";        
    }
}

print new superApplication;
?>

此行为未记录,因此我想知道它是错误还是功能,是否会导致安全问题?

更新 我知道静态方法中不允许使用$ this,这种行为出现在php 5.2.11版

1 个答案:

答案 0 :(得分:1)

在PHP 5.3中考虑这个例子:

<?php
        error_reporting(E_ALL | E_STRICT);

        class A
        {
                private $a = 'A';
                protected $b= 'B';
                public $c = 'C';
        }

        class B extends A
        {
                public function __construct()
                {
                        var_dump($this->a, $this->b, $this->c);
                        C::test();
                        var_dump($this->a, $this->b, $this->c);
                }
        }

        class C extends A
        {
                public function test()
                {
                        $this->a = null;
                        $this->b = null;
                        $this->c = null;
                }
        }

        new B();
?>

输出结果为:

PHP Notice:  Undefined property: B::$a in ... on line 15
NULL
string(1) "B"
string(1) "C"
PHP Strict Standards:  Non-static method C::test() should not be called statically, assuming $this from incompatible context in ... on line 16
NULL
NULL
NULL

假设C::test()的{​​{1}}指针假定为$this实例中的$this,会发生什么。所以它就像是B的成员函数,但有C的访问权。

它只能访问new B()中的受保护和公共变量以及A中的公共变量。

请注意,在致电B之前,C::test()已触发通知。在调用之后,它不再执行,因为变量是在调用中创建的。但在任何时候$this->a的私有变量都无法访问。

所以是的,严格来说,这被认为在PHP 5.3中无效。即使早期版本允许您在没有警告的情况下执行此操作(我没有检查或研究过),您也不应该依赖该行为,因为它显然是滥用OOP。