แสดงบทความที่มีป้ายกำกับ Programming แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ Programming แสดงบทความทั้งหมด

วันอังคารที่ 11 มีนาคม พ.ศ. 2568

[PHP] การใช้ isset() และ empty() ต่างกันอย่างไร?

ถ้าพูดถึง PHP ฟังก์ชันที่เกี่ยวกับการเช็กค่าตัวแปรสองตัวที่ถูกใช้บ่อยมาก ๆ ก็คือ isset() และ empty() หลายคนอาจจะงงว่ามันต่างกันยังไง? ใช้ตัวไหนเมื่อไหร่? วันนี้เราจะมาอธิบายให้เข้าใจแบบง่าย ๆ เหมือนนั่งคุยกับเพื่อน!

1. isset() คืออะไร?

isset() ใช้สำหรับตรวจสอบว่าตัวแปรนั้น ถูกกำหนดค่าแล้วหรือไม่ และ ไม่ได้เป็นค่า NULL ถ้าตัวแปรนั้นถูกกำหนดค่าแล้ว (ไม่ว่าจะเป็นค่าที่ว่างเปล่าแต่ไม่ใช่ NULL) มันจะคืนค่า true แต่ถ้าตัวแปรนั้นไม่มีอยู่หรือมีค่าเป็น NULL จะคืนค่า false

ตัวอย่างการใช้งาน isset()

$var1 = "Hello, PHP!";
$var2 = NULL;

var_dump(isset($var1)); // true
var_dump(isset($var2)); // false
var_dump(isset($var3)); // false เพราะ $var3 ไม่มีการประกาศ

2. empty() คืออะไร?

empty() ใช้เพื่อตรวจสอบว่าตัวแปร เป็นค่าที่ถือว่า "ว่างเปล่า" หรือไม่ หมายถึง ค่าเป็น NULL, 0, "" (สตริงว่าง), false, array() (อาร์เรย์ว่าง), หรือไม่มีการกำหนดค่ามาก่อน ถ้าตัวแปรอยู่ในสถานะ "ว่างเปล่า" มันจะคืนค่า true ถ้าไม่ว่างเปล่าจะคืนค่า false

ตัวอย่างการใช้งาน empty()

$var1 = ""; // สตริงว่าง
$var2 = 0;   // ศูนย์
$var3 = NULL;
$var4 = [];
$var5 = "Hello";

var_dump(empty($var1)); // true
var_dump(empty($var2)); // true
var_dump(empty($var3)); // true
var_dump(empty($var4)); // true
var_dump(empty($var5)); // false เพราะมันมีค่าจริงๆ

3. เปรียบเทียบ isset() และ empty()


สถานะของตัวแปร isset($var) empty($var)
ไม่ได้กำหนดค่า false true
NULL false true
false true true
0 true true
"" (สตริงว่าง) true true
"PHP" (สตริงที่มีค่า) true false
[] (อาร์เรย์ว่าง) true true

4. แล้วเราควรใช้ตัวไหน?

  • ถ้าต้องการ เช็กว่าตัวแปรถูกกำหนดค่าหรือไม่ ให้ใช้ isset()
  • ถ้าต้องการ เช็กว่าตัวแปรมีค่าที่ "ว่างเปล่า" หรือไม่ ให้ใช้ empty()

ตัวอย่างการใช้งานในชีวิตจริง

ใช้ isset() ตรวจสอบว่ามีค่าหรือไม่ก่อนใช้งาน

if (isset($_POST['username'])) {
    echo "Username: " . $_POST['username'];
} else {
    echo "กรุณากรอกชื่อผู้ใช้";
}

ใช้ empty() ตรวจสอบว่าค่าว่างหรือไม่

if (empty($_POST['password'])) {
    echo "กรุณากรอกรหัสผ่าน";
} else {
    echo "รหัสผ่านของคุณถูกบันทึกแล้ว";
}

5. ใช้ isset() และ empty() ร่วมกัน

บางกรณีเราอาจใช้ทั้งสองฟังก์ชันร่วมกัน เช่น

if (isset($_POST['email']) && !empty($_POST['email'])) {
    echo "อีเมลของคุณคือ " . $_POST['email'];
} else {
    echo "กรุณากรอกอีเมล";
}

ในกรณีนี้ isset() จะช่วยให้แน่ใจว่าตัวแปรถูกกำหนดแล้ว และ empty() จะช่วยให้แน่ใจว่ามันไม่ใช่ค่าที่ว่างเปล่า

6. ข้อควรระวังในการใช้ isset() และ empty()

  1. isset() ไม่สามารถตรวจสอบได้ว่าค่าตัวแปรว่างเปล่าหรือไม่
  2. empty() สามารถเช็กตัวแปรที่ไม่ได้ประกาศได้เลยโดยไม่เกิด Error
  3. ระวังเรื่องค่าของตัวเลข 0 เพราะ empty(0) จะคืนค่า true

ตัวอย่างที่ต้องระวัง:

$var = 0;
if (empty($var)) {
    echo "ตัวแปรนี้ว่าง";
} else {
    echo "ตัวแปรนี้มีค่า";
}
// ผลลัพธ์: ตัวแปรนี้ว่าง (เพราะ empty(0) ให้ค่าเป็น true)

7. สรุปแบบเข้าใจง่าย

  • isset($var): เช็กว่าตัวแปรถูกกำหนดค่าแล้ว และไม่ใช่ NULL
  • empty($var): เช็กว่าตัวแปร "ไม่มีค่า" หรือเป็นค่าที่ถือว่าว่างเปล่า
  • isset() คืนค่า false เมื่อตัวแปรเป็น NULL หรือไม่มีอยู่
  • empty() คืนค่า true เมื่อค่าของตัวแปรเป็น 0, "", false, NULL, array(), หรือไม่มีอยู่เลย
  • ควรใช้ isset() เช็กว่าตัวแปรมีอยู่หรือไม่ และ empty() เช็กว่าตัวแปรมีค่าหรือเปล่า

 

วันเสาร์ที่ 8 มีนาคม พ.ศ. 2568

PHP8 Constructor Property Promotion: ลดโค้ดซ้ำซ้อนในคลาส

ถ้าคุณเป็นสาย PHP และเคยเขียนคลาสในเวอร์ชันก่อน PHP 8 ก็คงเคยเจอปัญหานี้แน่ ๆ … "ทำไมต้องเขียน constructor เยอะขนาดนี้?"
จะประกาศ property ก็ต้องเขียน ต้องกำหนดค่าให้มันอีก แถมยังต้องรับค่ามาใน constructor และกำหนดค่าอีกที มันดูซ้ำซ้อนและวุ่นวายไปหมด

แต่พอมา PHP 8 ปุ๊บ! ก็เหมือนมีพระมาโปรด เพราะฟีเจอร์ Constructor Property Promotion ช่วยให้เราลดโค้ดที่ไม่จำเป็นไปได้เยอะมาก! วันนี้เราจะมาดูกันว่า มันคืออะไร ใช้งานยังไง และช่วยให้ชีวิตง่ายขึ้นได้แค่ไหน

1. ปัญหาของ Constructor ใน PHP เวอร์ชันก่อน

ก่อนจะเข้าเรื่องใหม่ ลองมาดูโค้ดของ PHP 7 กันก่อน สมมติว่าเราจะสร้างคลาส User ที่มี name และ email

class User {
    private string $name;
    private string $email;

    public function __construct(string $name, string $email) {
        $this->name = $name;
        $this->email = $email;
    }
}

เห็นอะไรมั้ย?

  • ต้องประกาศตัวแปร สองรอบ (ข้างบนและใน constructor)
  • ต้องกำหนดค่าให้ property ใน constructor ซึ่งดูเหมือนเป็นงานซ้ำซ้อน

ยิ่งถ้าคลาสมี property เยอะ เช่น age, address, phoneNumber ก็ต้องเพิ่ม constructor ยาวเหยียด ซึ่งไม่สนุกเลย!

2. Constructor Property Promotion ใน PHP 8

PHP 8 มาพร้อมกับฟีเจอร์ Constructor Property Promotion ที่ช่วยให้โค้ดสะอาดขึ้น ลดความซ้ำซ้อน โดยให้เราสามารถประกาศและกำหนดค่า property ได้ ใน constructor parameter list เลย

มาดูเวอร์ชันใหม่กัน

class User {
    public function __construct(
        private string $name,
        private string $email
    ) {}
}

จบ! แค่ 5 บรรทัด 🚀

อธิบายโค้ด

  • private string $name, private string $email อยู่ใน parameter list เลย
  • ไม่ต้องประกาศ property แยก
  • ไม่ต้องใช้ $this->name = $name; อีกต่อไป

ผลลัพธ์เหมือนเดิม แต่ โค้ดสั้นลง สะอาดขึ้น และอ่านง่ายขึ้น!

3. ตัวอย่างการใช้งานจริง

ใช้งานคลาสที่เขียนด้วย Constructor Property Promotion

$user = new User("John Doe", "john@example.com");

var_dump($user);

ง่ายเหมือนเดิม แต่โค้ดในคลาสสะอาดขึ้น
ใช้ร่วมกับ Visibility Modifier (public, protected, private)

คุณสามารถใช้ public, protected, หรือ private ได้ใน property ที่ประกาศไว้ใน constructor เช่น

class Product {
    public function __construct(
        public string $name,
        private float $price,
        protected int $stock
    ) {}
}

  • name เป็น public → สามารถเข้าถึงได้จากภายนอก
  • price เป็น private → ใช้ได้เฉพาะในคลาส
  • stock เป็น protected → ใช้ได้เฉพาะในคลาสและ subclass

เรียบง่ายกว่า PHP 7 เยอะ!

4. ใช้กับ readonly เพื่อให้ property ไม่เปลี่ยนค่า

PHP 8.1 เพิ่ม readonly ซึ่งใช้กับ Property Promotion ได้ด้วย เช่น

class Config {
    public function __construct(
        public readonly string $appName,
        public readonly string $version
    ) {}
}

ค่าของ appName และ version จะเปลี่ยนไม่ได้หลังจากกำหนดใน constructor

5. ใช้กับ default value ได้

Constructor Property Promotion ยังรองรับค่าเริ่มต้น เช่น

class Order {
    public function __construct(
        private int $quantity = 1,
        private string $status = "pending"
    ) {}
}

ถ้าสร้างออเดอร์ใหม่โดยไม่ส่งค่าเข้ามา ค่าเริ่มต้นก็จะถูกใช้

$order = new Order(); // quantity = 1, status = "pending"

6. ข้อจำกัดของ Constructor Property Promotion

ถึงแม้จะสะดวก แต่มันก็มีข้อจำกัด เช่น

❌ ไม่รองรับการกำหนดค่าแบบซับซ้อน
เช่น ถ้าต้องมีการคำนวณหรือดึงค่าจากฟังก์ชันอื่น จะใช้ Property Promotion ไม่ได้

class Invoice {
    public function __construct(
        private float $total = calculateTotal() // ❌ ใช้ไม่ได้
    ) {}
}

❌ ใช้กับ property ที่ต้องกำหนดค่าเริ่มต้นจากเงื่อนไขไม่ได้
ถ้าต้องมี logic ซับซ้อนใน constructor ต้องกลับไปใช้แบบเดิม เช่น

class Subscription {
    private string $status;

    public function __construct($isActive) {
        $this->status = $isActive ? "active" : "inactive"; // ✅ ใช้แบบนี้แทน
    }
}

7. ควรใช้ Constructor Property Promotion ตอนไหน?

✅ เมื่อ property เป็นค่าธรรมดา เช่น string, int, float, bool
✅ เมื่อ property ไม่ต้องการ logic เพิ่มเติมใน constructor
✅ เมื่ออยากให้โค้ดสะอาดขึ้นและอ่านง่ายขึ้น

แต่ถ้ามี logic ซับซ้อน ควรใช้แบบเดิม

สรุป

ฟีเจอร์ Constructor Property Promotion ใน PHP 8 ทำให้เราสามารถประกาศ property และกำหนดค่าได้ใน constructor parameter list เลย ไม่ต้องเขียนโค้ดซ้ำซ้อนแบบเดิมอีกต่อไป
🔥 จุดเด่น

✔ ลดโค้ดซ้ำซ้อน
✔ อ่านง่ายขึ้น
✔ ใช้ public, private, protected ได้เลย
✔ ใช้ readonly ได้
⚠ ข้อควรระวัง

❌ ใช้ไม่ได้กับ logic ซับซ้อน
❌ ใช้ไม่ได้กับ property ที่ต้องการค่าเริ่มต้นจากฟังก์ชัน

แต่โดยรวมแล้ว ช่วยให้การเขียน PHP สนุกขึ้นเยอะ! ใครยังไม่ได้ลอง ใช้เลย 🚀

วันพุธที่ 19 กุมภาพันธ์ พ.ศ. 2568

[PHP] การสืบทอดคลาส (Class Inheritance) : เข้าใจง่าย ใช้งานได้จริง!

การสืบทอดคลาส (Inheritance) คืออะไร?

ถ้าพูดถึงเรื่อง "มรดกตกทอด" ทุกคนคงเข้าใจกันดี เช่น พ่อแม่อาจจะส่งต่อบ้าน รถ หรือธุรกิจให้ลูก ๆ ได้ใช้งานต่อ ในโลกของการเขียนโปรแกรมก็มีแนวคิดแบบนี้เหมือนกัน ซึ่งเรียกว่า การสืบทอดคลาส (Class Inheritance)

ใน PHP (และภาษา OOP อื่น ๆ) การสืบทอดคลาสช่วยให้เราสร้างคลาสใหม่จากคลาสที่มีอยู่แล้ว โดยไม่ต้องเขียนโค้ดใหม่ทั้งหมด คลาสใหม่ (เรียกว่า คลาสลูก หรือ Subclass) จะได้รับคุณสมบัติ (Properties) และพฤติกรรม (Methods) จากคลาสเดิม (เรียกว่า คลาสแม่ หรือ Superclass) แบบอัตโนมัติ

พูดง่าย ๆ คือ เราไม่ต้องเริ่มจากศูนย์ แต่สามารถใช้ของที่มีอยู่แล้วมาต่อยอดได้เลย!

 

ทำไมต้องใช้การสืบทอดคลาส?

1. ลดโค้ดซ้ำซ้อน (Code Reusability) ถ้าเรามีโค้ดที่ใช้บ่อย ๆ ในหลายคลาส แทนที่จะก็อปปี้โค้ดไปวางซ้ำ ๆ เราสามารถให้คลาสลูกสืบทอดจากคลาสแม่เพื่อใช้โค้ดเดิมได้เลย

2. แก้ไขง่ายขึ้น (Easier Maintenance) ถ้าต้องการแก้ไขพฤติกรรมของคลาสหลาย ๆ ตัวที่คล้ายกัน เราแค่แก้ที่คลาสแม่ คลาสลูกทั้งหมดก็จะได้รับการเปลี่ยนแปลงโดยอัตโนมัติ

3. โครงสร้างโปรแกรมชัดเจน (Better Code Structure) ทำให้โปรแกรมมีโครงสร้างที่เป็นลำดับชั้น เข้าใจง่าย เช่น มีคลาส Animal เป็นคลาสแม่ และมี Dog, Cat, Bird เป็นคลาสลูก

4. รองรับการเขียนโปรแกรมเชิงวัตถุ (OOP Principles) ช่วยให้เราใช้หลักการ OOP อย่าง Encapsulation, Inheritance, และ Polymorphism ได้เต็มที่ 

 

ตัวอย่างโค้ด PHP: การสืบทอดคลาสแบบง่าย ๆ

มาดูกันว่าการสืบทอดคลาสใน PHP ทำงานอย่างไร

<?php
// คลาสแม่ (Superclass)
class Animal {
    public $name;

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

    public function makeSound() {
        return "เสียงสัตว์";
    }
}

// คลาสลูก (Subclass) สืบทอดจาก Animal
class Dog extends Animal {
    public function makeSound() {
        return "โฮ่ง โฮ่ง!";
    }
}

// ใช้งานจริง
$dog = new Dog("บ๊อบบี้");
echo $dog->name; // บ๊อบบี้
echo "<br>";
echo $dog->makeSound(); // โฮ่ง โฮ่ง!
?>


อธิบายโค้ด:

  • คลาส Animal เป็นคลาสแม่ มีคุณสมบัติ $name และเมธอด makeSound()
  • คลาส Dog เป็นคลาสลูก ใช้ extends เพื่อสืบทอดจาก Animal และเขียน makeSound() ใหม่ (Override)
  • ตอนสร้างอ็อบเจ็กต์ Dog เราสามารถใช้ $dog->name และ $dog->makeSound() ได้เลย!

 

parent:: เรียกใช้เมธอดจากคลาสแม่

บางครั้งเราต้องการใช้เมธอดของคลาสแม่ในคลาสลูก เช่น เราอยากให้ makeSound() ของ Dog ใช้เสียงของ Animal แล้วเติมคำเพิ่ม 

<?php
class Animal {
    public function makeSound() {
        return "เสียงสัตว์ทั่วไป";
    }
}

class Dog extends Animal {
    public function makeSound() {
        return parent::makeSound() . " และเสียงของหมาคือ โฮ่ง โฮ่ง!";
    }
}

$dog = new Dog();
echo $dog->makeSound(); // เสียงสัตว์ทั่วไป และเสียงของหมาคือ โฮ่ง โฮ่ง!
?>


อธิบายโค้ด:

  • parent::makeSound() คือการเรียกใช้เมธอด makeSound() จากคลาสแม่ แล้วเติมคำเพิ่ม

 

protected และ private มีผลกับการสืบทอดยังไง?

  • public = ใช้ได้ทุกที่ (ทั้งในคลาสแม่ คลาสลูก และจากภายนอก)
  • protected = ใช้ได้ในคลาสแม่และคลาสลูกเท่านั้น
  • private = ใช้ได้เฉพาะในคลาสที่ประกาศเท่านั้น (คลาสลูกมองไม่เห็น!)

มาดูตัวอย่างกัน 

<?php
class Animal {
    public $name = "สัตว์"; // ใช้ได้ทุกที่
    protected $color = "น้ำตาล"; // ใช้ได้ในคลาสแม่และลูก
    private $age = 5; // ใช้ได้แค่ในคลาสนี้เท่านั้น

    public function getAge() {
        return $this->age;
    }
}

class Dog extends Animal {
    public function getColor() {
        return $this->color; // ใช้ได้ เพราะเป็น protected
    }

    public function getAgeFromParent() {
        // return $this->age; //  Error! เพราะ age เป็น private
        return $this->getAge(); // ใช้ผ่านเมธอด public ของคลาสแม่ได้
    }
}

$dog = new Dog();
echo $dog->name; // ใช้ได้
// echo $dog->color; // Error! เพราะเป็น protected
// echo $dog->age; // Error! เพราะเป็น private
echo $dog->getColor(); // ใช้ได้
echo $dog->getAgeFromParent(); // ใช้ได้
?>


final ป้องกันการสืบทอดและ Override

ถ้าต้องการห้ามไม่ให้มีคลาสลูกสืบทอดจากคลาสแม่ ให้ใช้ final หน้า class

final class Animal {
    // โค้ดในคลาส
}

// class Dog extends Animal {} //  Error! เพราะ Animal เป็น final

หรือหากต้องการห้าม Override เมธอด ให้ใช้ final หน้า function

class Animal {
    final public function makeSound() {
        return "เสียงสัตว์ทั่วไป";
    }
}

class Dog extends Animal {
    // public function makeSound() {} //  Error! เพราะเมธอด makeSound() เป็น final
}
 

สรุปแนวคิดสำคัญเกี่ยวกับการสืบทอดคลาสใน PHP

  • ใช้ extends เพื่อให้คลาสลูกสืบทอดจากคลาสแม่
  • คลาสลูกได้รับทุกอย่างจากคลาสแม่ (ยกเว้น private)
  • ใช้ parent::method() เรียกเมธอดจากคลาสแม่
  • ใช้ protected เพื่อให้ใช้ได้ในคลาสแม่และลูก แต่ไม่ให้ใช้จากภายนอก
  • ใช้ final ถ้าต้องการห้ามสืบทอดหรือห้าม Override

การสืบทอดคลาสทำให้โค้ดสะอาดขึ้น ง่ายต่อการบำรุงรักษา และรองรับหลักการ OOP อย่างแท้จริง! ถ้าใครยังไม่ได้ลองใช้ในโปรเจกต์ของตัวเอง ลองเอาไปปรับใช้ดูนะ รับรองว่าชีวิตนักพัฒนาจะง่ายขึ้นแน่นอน!