PHP: Constructor Property Promotion เป็นฟีเจอร์ที่ถูกเพิ่มเข้ามาตั้งแต่ PHP 8.0 ซึ่งช่วยให้เราสามารถประกาศและกำหนดค่าให้กับ Property (ตัวแปรของคลาส) ได้โดยตรงภายใน Constructor เลย พูดง่าย ๆ คือมันช่วยลดโค้ดที่ซ้ำซ้อน (Boilerplate code) ลงไปได้เยอะมากครับ
เพื่อให้เห็นภาพชัดเจน ลองมาดูการเปรียบเทียบระหว่างแบบเดิม กับแบบใหม่กันครับ
เปรียบเทียบแบบเก่า vs แบบใหม่
สมมติว่าเราต้องการสร้างคลาส User ที่มี property 3 ตัวคือ id, name และ email
แบบเดิม (ก่อน PHP 8.0): เราต้องประกาศ Property ด้านบน ทำ Type hinting จากนั้นก็ต้องมาเขียนสั่ง $this->... = $... ซ้ำๆ อีกรอบใน constructor
class User {
public int $id;
public string $name;
public string $email;
public function __construct(int $id, string $name, string $email) {
$this->id = $id;
$this->name = $name;
$this->email = $email;
}
}
แบบใหม่ที่ใช้ Constructor Property Promotion:
เราสามารถใส่ Visibility Keyword (public, protected, private) ไว้ข้างหน้าพารามิเตอร์ใน constructor ได้เลย PHP จะเข้าใจทันทีว่าเราต้องการให้มันเป็นทั้ง Property ของคลาส และรับค่าไปพร้อมกัน
class User {
public function __construct(
public int $id,
public string $name,
public string $email
) {} // ตัว Body ของ constructor ปล่อยว่างไว้ได้เลยถ้าไม่มีลอจิกอื่น
}
ผลลัพธ์: โค้ดสั้นลง อ่านง่ายขึ้น และลดโอกาสเขียนชื่อตัวแปรผิดไปได้เยอะเลยครับ
กฎและข้อควรรู้ในการใช้งาน
แม้ว่าจะสะดวกมาก แต่ก็มีข้อกำหนดบางอย่างที่ต้องระวังครับ
- ต้องมี Visibility Keyword เสมอ: ถ้าเราไม่ใส่
public,protected, หรือprivateหน้าพารามิเตอร์ PHP จะมองว่าเป็นพารามิเตอร์ของฟังก์ชันธรรมดา ไม่ใช่การทำ Property Promotion - กำหนด Default Value ได้ตามปกติ: เราสามารถใส่ค่าเริ่มต้นให้ตัวแปรได้เหมือนเดิม
public function __construct(public string $role = 'guest') {} - ทำงานร่วมกับพารามิเตอร์ปกติได้: ใน constructor เดียวกัน สามารถมีทั้งตัวแปรธรรมดา และตัวแปรที่ทำ Promotion ร่วมกันได้
public function __construct( public string $name, $normalArgument // ตัวนี้จะเป็นแค่ตัวแปรธรรมดา ไม่ถูกสร้างเป็น property ของคลาส ) {} - ไม่สามารถใช้กับ Abstract Constructor ได้: เพราะคลาสที่เป็น Abstract หรือ Interface ไม่มีการทำงานของตัว body ใน constructor จริง ๆ
- ใช้กับ Callable Type ไม่ได้: เราไม่สามารถใช้
callableเป็น Type ของ promoted property ได้เนื่องจากข้อจำกัดของโครงสร้าง PHP Engine
แล้วถ้ายังอยากมี Logic ใน Constructor ล่ะ?
ถ้าเราจำเป็นต้องเช็คความถูกต้องของข้อมูล (Validation) ก่อนบันทึกค่า ก็ยังสามารถเขียนโค้ดลงไปใน {} ของ constructor ได้ตามปกติครับ เพราะ PHP จะแอบแปลงโค้ดและส่งค่าเข้า property ให้เราก่อนที่โค้ดใน {} จะทำงาน
class Product {
public function __construct(
public string $name,
public float $price
) {
// สามารถเขียน logic ตรวจสอบต่อได้ทันที
if ($this->price < 0) {
throw new InvalidArgumentException("ราคาติดลบไม่ได้นะ!");
}
}
}
อ่านเพิ่มเติม