วิธีการคงที่สามารถเข้าถึงออบเจ็กต์ผู้โทร บั๊ก หรือฟีเจอร์ได้

ฉันกำลังทำงานกับแอปพลิเคชันของฉันและค้นพบพฤติกรรมแปลก ๆ ของวิธีการที่เรียกว่าแบบคงที่แต่ไม่ได้ถูกกำหนดให้เป็นแบบคงที่ที่ขยายคลาสเดียวกัน ในที่สุดวิธีนี้ก็สามารถเข้าถึงและแก้ไขตัวแปรและวิธีการป้องกันผู้โทรได้ นี่คือตัวอย่างรหัสของฉัน:

<?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


person Nazariy    schedule 12.09.2010    source แหล่งที่มา


คำตอบ (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

สิ่งที่เกิดขึ้นคือตัวชี้ $this ของ C::test() จะถือว่าเป็น $this จากอินสแตนซ์ new B() มันเลยทำหน้าที่เหมือนกับฟังก์ชันสมาชิกของ B แต่ด้วยการเข้าถึงของ C

สามารถเข้าถึงได้เฉพาะตัวแปรที่ได้รับการป้องกันและสาธารณะจาก A และตัวแปรสาธารณะจาก B

โปรดทราบว่าก่อนที่จะโทรไปที่ C::test() $this->a จะแจ้งเตือน หลังจากการเรียก จะไม่ทำอีกต่อไป เนื่องจากมีการสร้างตัวแปรภายในการโทร แต่ถึงจุดๆ หนึ่งก็ไม่สามารถเข้าถึงตัวแปรส่วนตัวของ A ได้

ใช่ นี่เป็นการพูดอย่างเคร่งครัด ซึ่งถือว่าไม่ถูกต้องใน PHP 5.3 และแม้ว่าเวอร์ชันก่อนหน้านี้จะให้คุณทำเช่นนี้โดยไม่มีการเตือนล่วงหน้า (ฉันไม่ได้ตรวจสอบหรือค้นคว้าข้อมูลนั้น) คุณไม่ควรพึ่งพาพฤติกรรมนั้น เนื่องจากเห็นได้ชัดว่าเป็นการละเมิด OOP

person Matthew    schedule 16.09.2010