ข้ามไปยังเนื้อหา

รากฐานของ PHP 8.4

Spec: ISO 32000-2, §7.5.2 Evidence: Code-backed ข้อจำกัด PHP: ≥8.4 <9.0

NextPDF ต้องใช้ PHP 8.4 หน้านี้อธิบายว่าเอนจินพึ่งพาคุณสมบัติด้านภาษาใดของ 8.4 เหตุใดเวอร์ชันนี้จึงเป็นขีดต่ำสุดที่บังคับใช้จริง ไม่ใช่เพียงคำแนะนำ และบิลด์ดาวน์เกรดแยกต่างหากช่วยให้ยังรันบนรันไทม์รุ่นเก่าได้อย่างไรโดยไม่ทำให้โค้ดเบสที่คุณอ่านอ่อนแอลง

เอนจิน PDF แปลงอินพุตที่กำกวมให้เป็นรูปแบบไฟล์ที่แม่นยำระดับไบต์ PDF เป็นรูปแบบที่มีมานานและมีกฎเกณฑ์ที่มั่นคงตายตัว อีกทั้งเข้มงวดมากพอที่การคาดเดาผิดจะมีต้นทุนสูง ภาษาที่ใช้เขียนเอนจินเป็นจุดแรกที่การคาดเดาเหล่านั้นจะถูกตรวจจับหรือปล่อยผ่านไปโดยไม่ตรวจสอบ ขีดต่ำสุดของเวอร์ชันไม่ใช่ข้อจำกัดที่ตั้งขึ้นเพื่อตัวมันเอง แต่เป็นเส้นแบ่งที่หากต่ำกว่านั้น เอนจินจะไม่สามารถให้การรับประกันด้านชนิดข้อมูลที่ส่วนอื่นของการออกแบบพึ่งพาได้อีกต่อไป

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

  • แพ็กเกจ core ประกาศ "php": ">=8.4 <9.0" นั่นคือข้อจำกัดจริงที่ยืนยันได้ใน composer.json ไม่ใช่เพียงความตั้งใจในเอกสาร
  • 8.4 เป็นขีดต่ำสุดเพราะเอนจินใช้คุณสมบัติด้านภาษาของ 8.4 (และ 8.x รุ่นล่าสุด) ให้เป็นการรับประกันเชิงโครงสร้าง ได้แก่ asymmetric visibility, backed enum ที่มีพฤติกรรม, typed class constant, สถานะ readonly และ named argument ระดับ first-class ใน public API
  • การรันบน PHP 8.1–8.3 ยังคงเป็นไปได้ผ่าน บิลด์ดาวน์เกรดแยกต่างหาก (backport) บิลด์นี้เป็นเครื่องมือสำหรับการบิลด์ ไม่ใช่ dependency ของรันไทม์ และไม่ได้เปลี่ยนแปลงโค้ดที่คุณอ่านในรีพอซิทอรี core
  • ขีดจำกัดบน <9.0 ตั้งใจไว้เช่นนั้น เพราะ PHP รุ่นเมเจอร์ใหม่ถือเป็นสิ่งที่ต้องตรวจสอบยืนยัน ไม่ใช่สิ่งที่จะสันนิษฐานไว้ก่อน

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

Asymmetric visibility ทำให้สถานะอ่านได้แบบ public แต่เขียนได้เฉพาะแบบ private โดยไม่ต้องเขียน getter ด้วยมือให้ทุกฟิลด์ บริบทการเรนเดอร์ใช้คุณสมบัตินี้โดยตรง:

declare(strict_types=1);
final class RenderingContext
{
// Readable everywhere, writable only inside the class.
public private(set) float $x = 0.0;
public private(set) float $y = 0.0;
public private(set) int $currentPageIndex = -1;
public private(set) string $currentContentStream = '';
}

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

Backed enum ที่มีพฤติกรรม เข้ามาแทนที่แฟล็ก boolean และค่าคงที่ string ที่กระจัดกระจายด้วยค่าที่มีชนิดข้อมูลเดียวและตอบคำถามเกี่ยวกับตัวเองได้ ตัวระบุความสอดคล้องของเอกสารเป็น backed enum ซึ่งเมธอดของมันใช้ตัดสินผลลัพธ์ในระดับสเปก:

declare(strict_types=1);
enum ConformanceMode: string
{
case Plain = 'plain';
case PdfUa2 = 'pdfua2';
case PdfA4 = 'pdfa4';
case PdfA4f = 'pdfa4f';
public function isTagged(): bool
{
return match ($this) {
self::Plain => false,
default => true,
};
}
/** @return 2|3|4|null */
public function pdfaPart(): ?int
{
return match ($this) {
self::PdfA4, self::PdfA4f => 4,
default => null,
};
}
}

enum นี้เป็นแหล่งความจริงเพียงแห่งเดียวสำหรับคำถาม “เอกสารนี้ติดแท็กตามสเปกหรือไม่?” และ “ใช้ ISO ส่วนใด?” เมื่อคำถามเหล่านั้นถูกแสดงเป็น boolean แบบหลวมๆ หลายจุดอาจตอบได้ไม่สอดคล้องกัน

Typed class constant ทำให้แม้แต่ค่าคงที่ก็เป็นส่วนหนึ่งของสัญญาด้านชนิดข้อมูล ขีดจำกัดที่เข้มงวดของเอนจิน HTML ถูกประกาศเป็น typed constant:

private const int MAX_NESTING_DEPTH = 100;
private const int MAX_ELEMENT_COUNT = 50_000;

Named argument เป็นส่วนหนึ่งของพื้นผิว public API ไม่ใช่เพียงเทคนิคภายใน โปรแกรมตัวอย่างส่ง named argument เหล่านี้ ณ จุดเรียกใช้ซึ่งผู้อ่านควรคัดลอกไปใช้:

$doc->cell(0, 15, 'Hello, NextPDF!', newLine: true);

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

หน้านี้เป็น Evidence: Code-backed ทุกข้อกล่าวอ้างข้างต้นเชื่อมโยงไปยังไฟล์ในรีพอซิทอรี core ไม่ใช่เพียงรายการคุณสมบัติ:

  • ข้อจำกัดเวอร์ชันคือค่า require.php ">=8.4 <9.0" ในไฟล์ composer.json ของ core
  • ตัวอย่าง asymmetric-visibility คือสไตล์การประกาศที่ใช้จริงใน src/Core/RenderingContext.php (ฟิลด์ public private(set))
  • ตัวอย่าง enum สะท้อนถึง src/Conformance/ConformanceMode.php ซึ่งเป็น backed enum … : string ที่เมธอดซึ่งอิงกับ match ขับเคลื่อนการตัดสินใจด้านความสอดคล้อง
  • typed constant อยู่ใน src/Html/HtmlParser.php (private const int MAX_NESTING_DEPTH, MAX_ELEMENT_COUNT)
  • การเรียกใช้ named-argument มาจากโปรแกรมใน examples/ ที่จัดส่งไปด้วย

ขีดต่ำสุดยังมีมิติด้านมาตรฐานอีกด้วย หน้าที่ของเอนจินคือการสร้างไฟล์ที่สอดคล้องกับ Spec: ISO 32000-2, §7.5.2 ซึ่งกำหนดว่าตัวเขียน PDF 2.0 ที่สอดคล้องตามมาตรฐาน ต้องประกาศเวอร์ชันของเอกสารเป็น 2.0 ในส่วนหัวไฟล์หรือใน catalog การปฏิบัติตามข้อผูกพันที่แม่นยำเช่นนี้ทำได้ง่ายกว่ามากเมื่อภาษา ที่อยู่เบื้องหลังตัวเขียนทำให้สร้างสถานะที่ไม่สอดคล้องได้ยากตั้งแต่ แรก ขีดต่ำสุดของเวอร์ชันและความเข้มงวดของรูปแบบจึงไปในทิศทางเดียวกัน

โปรแกรมที่ถูกต้องขนาดเล็กที่สุดก็ใช้ขีดต่ำสุดนี้แล้ว โปรแกรมนี้รันบน PHP 8.4 ใช้ named argument และสร้างไฟล์ที่สอดคล้องตามมาตรฐาน:

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();
$doc->setTitle('Hello World');
$doc->addPage();
$doc->setFont('helvetica', '', 24);
$doc->cell(0, 15, 'Hello, NextPDF!', newLine: true);
$doc->save(__DIR__ . '/hello.pdf');

ไม่มีอะไรในนี้ที่พิเศษผิดปกติ ประเด็นคือกลไก strict-typing, enum และ asymmetric-visibility ชุดเดียวกันที่ทำให้ส่วนภายในของเอนจินน่าเชื่อถือนั้นทำงานอยู่แล้วภายใต้โปรแกรมห้าบรรทัดนี้ คุณไม่จำเป็นต้องเลือกเปิดใช้งานเอง

การตีความผิดที่พบบ่อยที่สุดคือ “ต้องใช้ PHP 8.4” หมายความว่า “จะไม่ทำงานหากคุณไม่อัปเกรดเป็น 8.4” ความหมายที่แท้จริงคือ ซอร์ส core มุ่งเป้าไปที่ 8.4 และมีบิลด์ดาวน์เกรดแยกต่างหากสำหรับทีมที่ถูกตรึงไว้ที่ PHP 8.1–8.3

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

หน้านี้อธิบาย เหตุใด 8.4 จึงเป็นขีดต่ำสุดและ สิ่งใด ที่ backport รักษาไว้ หน้านี้ไม่ได้ครอบคลุมวิธีรันไพป์ไลน์ดาวน์เกรด เวอร์ชันเป้าหมายที่รองรับ หรือข้อควรระวังในการใช้งาน สิ่งเหล่านั้นอยู่ในเอกสารของบิลด์ backport เอง โครงสร้างแพ็กเกจภายในของเครื่องมือนั้นอยู่นอกขอบเขตของหน้านี้ การใช้คุณสมบัติที่แสดงไว้เป็นเพียงตัวอย่างที่สื่อถึงสไตล์ของเอนจิน ไม่ใช่รายการครบถ้วนของทุกคุณสมบัติของ 8.x ที่โค้ดเบสใช้ API ที่แม่นยำกำหนดโดยเอกสารอ้างอิง ไม่ใช่โดยคำอธิบายนี้ ข้อจำกัดของเวอร์ชันถูกต้อง ณ วันที่ตรวจทานของหน้านี้ ค่าที่ถือเป็นบรรทัดฐานเสมอคือบล็อก require ในไฟล์ composer.json ของ core

รุ่น (edition) ไม่มีผลต่อขีดต่ำสุดของภาษา ทุกรุ่นถูกบิลด์จากซอร์ส PHP 8.4 ชุดเดียวกัน:

ขีดต่ำสุดของซอร์ส PHP 8.4 — edition availability
Edition Availability
Core Core เขียนขึ้นโดยใช้ PHP 8.4
Pro Pro สร้างขึ้นบนขีดต่ำสุดของซอร์ส 8.4 ชุดเดียวกัน
Enterprise Enterprise สร้างขึ้นบนขีดต่ำสุดของซอร์ส 8.4 ชุดเดียวกัน
  • Strict types, everywhere — ระเบียบวินัยด้านการวิเคราะห์เชิงสถิตเปลี่ยนขีดต่ำสุดของภาษาให้เป็นการรับประกันได้อย่างไร
  • The pipeline model — สถาปัตยกรรมที่ยึดโยงคุณสมบัติด้านภาษาเหล่านั้นเข้าด้วยกัน
  • The NextPDF design philosophy — เหตุใดเอนจินจึงให้ความสำคัญกับสัญญาที่ชัดเจนและบังคับใช้โดยรันไทม์
  • Version floor — เวอร์ชัน PHP ขั้นต่ำที่ซอร์ส core มุ่งเป้าไปที่ (>=8.4) ต่ำกว่านั้น การรับประกันด้านชนิดข้อมูลของเอนจินไม่สามารถแสดงออกได้
  • Asymmetric visibility — คุณสมบัติของ PHP 8.4 ที่ทำให้พร็อพเพอร์ตีอ่านได้แบบ public แต่เขียนได้เฉพาะจากขอบเขตที่แคบกว่าเท่านั้น (public private(set))
  • Backed enum — enum ของ PHP ที่แต่ละ case มีค่า scalar และสามารถมีพฤติกรรม (เมธอด) ได้ ในที่นี้ใช้เป็นแหล่งความจริงแบบมีชนิดข้อมูลเพียงแห่งเดียว
  • Backport — บิลด์ดาวน์เกรดแยกต่างหากที่อิงกับ Rector ซึ่งแปลงซอร์ส 8.4 ให้เป็นเอาต์พุตที่รันได้บน PHP รุ่นเก่า เป็นเครื่องมือสำหรับการบิลด์ ไม่ใช่ dependency ของรันไทม์
  • Conformance mode — ตัวระบุแบบมีชนิดข้อมูลของเอนจินสำหรับบอกว่าเอกสารต้องเป็นไปตามสัญญาความสอดคล้องของ ISO ฉบับใด