เหตุใดฉันจึงได้รับข้อผิดพลาด“ คุณสมบัติที่พิมพ์ต้องไม่สามารถเข้าถึงได้ก่อนเริ่มต้น” เมื่อแนะนำคำแนะนำประเภทคุณสมบัติ?


10

ฉันได้อัพเดตคำจำกัดความของคลาสของฉันเพื่อใช้ประโยชน์จากคำแนะนำประเภทคุณสมบัติที่แนะนำใหม่เช่นนี้:

class Foo {

    private int $id;
    private ?string $val;
    private DateTimeInterface $createdAt;
    private ?DateTimeInterface $updatedAt;

    public function __construct(int $id) {
        $this->id = $id;
    }


    public function getId(): int { return $this->id; }
    public function getVal(): ?string { return $this->val; }
    public function getCreatedAt(): ?DateTimeInterface { return $this->createdAt; }
    public function getUpdatedAt(): ?DateTimeInterface { return $this->updatedAt; }

    public function setVal(?string $val) { $this->val = $val; }
    public function setCreatedAt(DateTimeInterface $date) { $this->createdAt = $date; }
    public function setUpdatedAt(DateTimeInterface $date) { $this->updatedAt = $date; }
}

แต่เมื่อพยายามที่จะบันทึกเอนทิตีของฉันบนหลักคำสอนฉันได้รับข้อผิดพลาดว่า:

คุณสมบัติตัวอย่างต้องไม่สามารถเข้าถึงได้ก่อนเริ่มต้น

สิ่งนี้ไม่เพียงเกิดขึ้นกับ$idหรือ$createdAtเท่านั้น แต่ยังเกิดขึ้นกับ$valueหรือ$updatedAtซึ่งเป็นคุณสมบัติที่มีค่าเป็นโมฆะ

คำตอบ:


20

เนื่องจาก PHP 7.4 แนะนำการแนะนำชนิดของคุณสมบัติจึงเป็นสิ่งสำคัญอย่างยิ่งที่จะต้องให้ค่าที่ถูกต้องสำหรับคุณสมบัติทั้งหมดเพื่อให้คุณสมบัติทั้งหมดมีค่าที่ตรงกับประเภทที่ประกาศไว้

ตัวแปรที่ไม่เคยได้รับมอบหมายไม่ได้มีnullค่า แต่ก็เป็นในundefinedรัฐที่จะไม่ตรงกับชนิดของการประกาศใดundefined !== null.

สำหรับรหัสข้างต้นถ้าคุณทำ:

$f = new Foo(1);
$f->getVal();

คุณจะได้รับ:

ข้อผิดพลาดร้ายแรง: ข้อผิดพลาดที่ไม่ได้อ่าน: คุณสมบัติที่พิมพ์แล้ว Foo :: $ val ต้องไม่สามารถเข้าถึงได้ก่อนเริ่มต้น

เนื่องจาก$valไม่ใช่stringหรือnullเมื่อเข้าถึง

วิธีที่จะหลีกเลี่ยงปัญหานี้คือการกำหนดค่าให้กับคุณสมบัติทั้งหมดของคุณที่ตรงกับประเภทที่ประกาศไว้ คุณสามารถทำสิ่งนี้เป็นค่าเริ่มต้นสำหรับคุณสมบัติหรือในระหว่างการก่อสร้างทั้งนี้ขึ้นอยู่กับการตั้งค่าของคุณและประเภทของทรัพย์สิน

ตัวอย่างเช่นสำหรับข้างต้นคุณสามารถทำ:

class Foo {

    private int $id;
    private ?string $val = null; // <-- declaring default null value for the property
    private DateTimeInterface $createdAt;
    private ?DateTimeInterface $updatedAt;

    public function __construct(int $id) {
        // and on the constructor we set the default values for all the other 
        // properties, so now the instance is on a valid state
        $this->id = $id;
        $this->createdAt = new DateTimeImmutable();
        $this->updatedAt = new DateTimeImmutable();
    }

ตอนนี้คุณสมบัติทั้งหมดจะมีค่าที่ถูกต้องและอินสแตนซ์จะอยู่ในสถานะที่ถูกต้อง

สิ่งนี้สามารถเกิดขึ้นบ่อยครั้งเมื่อคุณพึ่งพาค่าที่มาจากฐานข้อมูลสำหรับค่าเอนทิตี เช่นรหัสที่สร้างขึ้นอัตโนมัติหรือการสร้างและ / หรือค่าที่อัปเดต ซึ่งมักจะถูกทิ้งไว้เป็นข้อกังวล DB

สำหรับรหัสสร้างขึ้นโดยอัตโนมัติวิธีที่แนะนำไปข้างหน้า?int $id = nullคือการเปลี่ยนการประกาศประเภทที่จะ สำหรับส่วนที่เหลือทั้งหมดเพียงเลือกค่าที่เหมาะสมสำหรับประเภทของคุณสมบัติ


-5

ข้อผิดพลาดของฉัน:

"Typed property Proxies\\__CG__\\App\\Entity\\Organization::$ must not be accessed before initialization (in __sleep)"

โซลูชันของฉัน - เพิ่มวิธีถัดไปในชั้นเรียน:

public function __sleep()
{
    return [];
}

1
โปรดอ่านคำถามให้ถูกต้องจากนั้นตอบตามคำถามไม่ใช่ปัญหาของคุณทั้งหมด
MAChitgarha
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.