Kodokon kodokon.com

PHP สมัยใหม่: strict types, enum, match

นำ PHP ยุคปัจจุบันมาใช้: strict types, arrow function, ตัวดำเนินการ nullsafe, enum และนิพจน์ match

9 นาที · 3 คำถาม

เปิดบทเรียนนี้ใน Kodokon

PHP สมัยใหม่โอบรับการกำหนดชนิด declare(strict_types=1) ที่วางไว้เป็นคำสั่งแรกของไฟล์ จะปิดการแปลงชนิดโดยปริยาย การส่งสายอักขระ '10' ให้พารามิเตอร์ชนิด float จะโยน TypeError แทนที่จะถูกแปลงเงียบ ๆ จงกำหนดชนิดให้กับ พารามิเตอร์และค่าที่คืนกลับ ข้อผิดพลาดของคุณจะปรากฏขึ้นแต่เนิ่น ๆ ในที่ที่ถูกต้อง แทนที่จะโผล่มาอีกสามไฟล์ถัดไป

PHP
<?php

declare(strict_types=1);

function applyDiscount(
    float $price,
    float $rate = 0.1
): float {
    return round($price * (1 - $rate), 2);
}

echo applyDiscount(49.99);
echo PHP_EOL;
echo applyDiscount(100.0, 0.25);
ลายเซ็นที่กำหนดชนิด: สัญญาของฟังก์ชันชัดเจน

Arrow function fn ย่นย่อฟังก์ชันนิรนามที่มีเพียงนิพจน์เดียว ข้อได้เปรียบสำคัญเหนือโคลเชอร์แบบดั้งเดิม: มันจับตัวแปรจากขอบเขตแม่โดยอัตโนมัติ โดยไม่ต้องใช้อนุประโยค use มันโดดเด่นเมื่อใช้กับ array_map() และ array_filter()

PHP
<?php

declare(strict_types=1);

$prices = [12.5, 49.9, 8.0, 120.0];
$rate = 0.2;

$discounted = array_map(
    fn (float $p): float => round($p * (1 - $rate), 2),
    $prices
);

$affordable = array_filter(
    $discounted,
    fn (float $p): bool => $p < 50
);

print_r($affordable);
ตัวแปร rate ถูกจับโดยไม่ต้องใช้อนุประโยค use

ตัวดำเนินการ nullsafe ?-> จะตัดการเรียกให้ลัดวงจรทันทีที่ข้อต่อในสายโซ่เป็น null แทนที่จะทำให้เกิดข้อผิดพลาดร้ายแรง เมื่อผสมกับ ?? มันจะแทนที่พีระมิดของคำสั่ง if ด้วยบรรทัดเดียวที่อ่านง่าย

PHP
<?php

declare(strict_types=1);

class Address
{
    public function __construct(
        public readonly string $city
    ) {
    }
}

class User
{
    public function __construct(
        public readonly ?Address $address = null
    ) {
    }
}

$alice = new User(new Address('Lyon'));
$bob = new User();

echo $alice->address?->city ?? 'Unknown city';
echo PHP_EOL;
echo $bob->address?->city ?? 'Unknown city';
ไม่มีข้อผิดพลาดสำหรับ Bob: สายโซ่หยุดที่ null ตัวแรก

Enum มอบชนิดที่แท้จริงให้กับชุดค่าที่ปิดตายตัว (สถานะ บทบาท) จนเป็นไปไม่ได้ที่จะสร้างสถานะที่ไม่มีอยู่จริง และ match คือการพัฒนาที่ชัดเจนเหนือ switch เปรียบเทียบอย่างเข้มงวด คืนผลลัพธ์ออกมาเป็นค่า และมี UnhandledMatchError หากไม่มีกรณีใดตรงกัน เป็นเกราะป้องกันความหลงลืม

PHP
<?php

declare(strict_types=1);

enum OrderStatus: string
{
    case Pending = 'pending';
    case Shipped = 'shipped';
    case Delivered = 'delivered';

    public function label(): string
    {
        return match ($this) {
            self::Pending => 'Pending',
            self::Shipped => 'Shipped',
            self::Delivered => 'Delivered',
        };
    }
}

$status = OrderStatus::from('shipped');
echo $status->label();
enum ที่หนุนด้วยสายอักขระ: เหมาะอย่างยิ่งสำหรับฐานข้อมูล

ทดสอบความรู้

ตรวจสอบว่าคุณจำประเด็นสำคัญของบทเรียนนี้ได้ครบถ้วน

  1. เมื่อมี declare(strict_types=1) จะเกิดอะไรขึ้นถ้าคุณส่งสายอักขระ '10' ให้พารามิเตอร์ชนิด float?
    • PHP แปลงสายอักขระเป็น 10.0 อย่างเงียบ ๆ
    • PHP แจ้งเพียงคำเตือนแล้วทำงานต่อ
    • PHP โยน TypeError
  2. อะไรที่ทำให้ arrow function fn() ต่างจากโคลเชอร์แบบดั้งเดิม function()?
    • มันสามารถบรรจุหลายคำสั่งได้
    • มันจับตัวแปรจากขอบเขตแม่โดยอัตโนมัติ โดยไม่ต้องใช้อนุประโยค use
    • มันทำงานเร็วกว่า
    • มันไม่สามารถกำหนดชนิดได้
  3. นิพจน์ match มีข้อได้เปรียบอะไรเหนือ switch?
    • มันเปรียบเทียบอย่างเข้มงวด (===) คืนค่าออกมา และโยนข้อผิดพลาดหากไม่มีกรณีใดตรงกัน
    • มันยอมรับการเปรียบเทียบแบบหลวม (==) เพื่อความยืดหยุ่นที่มากขึ้น
    • มันอนุญาตให้ไหลผ่านจากกรณีหนึ่งไปยังกรณีถัดไป