Статический метод может получить доступ к вызывающему объекту, багу или функции? - PullRequest
1 голос
/ 12 сентября 2010

Я работал над своим приложением и обнаружил странное поведение методов, которые вызывались статически, но не определялись как статические, расширяющие тот же класс. В конце концов, эти методы могут обращаться к переменным и методам, защищенным вызывающей стороной, и изменять их Вот пример моего кода:

<code><?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("
Исходный код
% s
", highlight_file (__ FILE__, true)); } } класс superApplication расширяет объект { публичная функция __toString () { echo "\ nВызывать сторонний объект статически, как thirdParty :: method () \ n"; echo thirdParty :: method (); echo "\ nВызов статического объекта третьей стороны через call_user_func () \ n"; echo call_user_func (array ('thirdParty', 'method')); echo sprintf («Параметры нового объекта \ n% s», print_r ($ this, true)); return sprintf ("% s: done \ n", $ this-> objectName); } } класс thirdParty расширяет объект { метод публичной функции () { если (is_object ($ это)) { $ this-> alteredBy = __CLASS__; возвратный спринтф ( " Объект '% s' был успешно изменен% s классом \ n", get_class ($ это), __УЧЕБНЫЙ КЛАСС__ ); } else return "Невозможно получить доступ к объекту вызывающей стороны \ n \ n"; } } распечатать новое суперприложение; ?>

Это поведение не задокументировано, поэтому мне интересно, это ошибка или функция и может ли это привести к проблемам безопасности?

UPDATE. Я знаю, что $ это не разрешено внутри статических методов, и это поведение появилось в php версии 5.2.11

1 Ответ

1 голос
/ 16 сентября 2010

Рассмотрим этот пример в 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() $this считается $this из экземпляра new B(). Таким образом, он действует как функция-член B, но с доступом к C.

Доступ к защищенным и общедоступным переменным возможен только из A, а к общедоступным переменным - B.

Обратите внимание, что перед вызовом C::test(), $this->a вызвало уведомление. После вызова он больше не выполнялся, поскольку переменная была создана в ходе вызова. Но ни в коем случае закрытые переменные A не были доступны.

Так что да, это, строго говоря, считается недействительным в PHP 5.3. И даже если более ранние версии позволяют вам делать это без предупреждения (я не проверял и не исследовал это), вы никогда не должны полагаться на такое поведение, поскольку это, очевидно, злоупотребление ООП.

...