มีอะไรใหม่ใน PHP 8.2 — คุณลักษณะใหม่ การเลิกใช้งาน การเปลี่ยนแปลง และอื่นๆ
เผยแพร่แล้ว: 2022-08-09PHP 8.2 สร้างขึ้นบนฐานการต่ออายุที่กำหนดโดย PHP 8.0 และ PHP 8.1 มีกำหนดเข้าฉาย 24 พฤศจิกายน 2545
บทความนี้จะครอบคลุมถึงสิ่งใหม่ใน PHP 8.2 โดยละเอียด — ตั้งแต่คุณสมบัติและการปรับปรุงใหม่ไปจนถึงการเลิกใช้งานและการเปลี่ยนแปลงเล็กน้อย เราจะดำเนินการทั้งหมด
เนื่องจาก PHP 8.2 เข้าสู่ฟีเจอร์หยุดทำงานในวันที่ 19 กรกฎาคม พ.ศ. 2565 คุณจึงคาดว่าจะไม่มีส่วนเพิ่มเติมที่สำคัญในรายการนี้
ตื่นเต้น? เราก็ด้วย
เอาล่ะ!
คุณลักษณะและการปรับปรุงใหม่ใน PHP 8.2
เริ่มต้นด้วยการสำรวจคุณสมบัติ PHP 8.2 ล่าสุดทั้งหมด เป็นรายการที่ค่อนข้างกว้างขวาง:
คลาส readonly
ใหม่
PHP 8.1 แนะนำคุณลักษณะแบบ readonly
อย่างเดียวสำหรับคุณสมบัติของคลาส ตอนนี้ PHP 8.2 กำลังเพิ่มการสนับสนุนเพื่อประกาศคลาสทั้งหมดเป็นแบบ readonly
อย่างเดียว
หากคุณประกาศคลาสเป็นแบบ readonly
อย่างเดียว คุณสมบัติทั้งหมดของคลาสนั้นจะสืบทอดคุณสมบัติแบบ readonly
อย่างเดียวโดยอัตโนมัติ ดังนั้น การประกาศคลาสแบบ readonly
อย่างเดียวก็เหมือนกับการประกาศคุณสมบัติของคลาสเป็นแบบ readonly
อย่างเดียว
ตัวอย่างเช่น ใน PHP 8.1 คุณต้องเขียนโค้ดที่น่าเบื่อนี้เพื่อประกาศคุณสมบัติคลาสทั้งหมดเป็นแบบ readonly
อย่างเดียว:
class MyClass { public readonly string $myValue, public readonly int $myOtherValue public readonly string $myAnotherValue public readonly int $myYetAnotherValue }
ลองนึกภาพเช่นเดียวกันกับคุณสมบัติอื่น ๆ อีกมากมาย ตอนนี้ ด้วย PHP 8.2 คุณสามารถเขียนสิ่งนี้ได้:
readonly class MyClass { public string $myValue, public int $myOtherValue public string $myAnotherValue public int $myYetAnotherValue }
คุณยังสามารถประกาศคลาสนามธรรมหรือคลาสสุดท้ายเป็นแบบ readonly
อย่างเดียว ที่นี่ ลำดับของคำหลักไม่สำคัญ
abstract readonly class Free {} final readonly class Dom {}
คุณยังสามารถประกาศคลาสแบบ readonly
อย่างเดียวโดยไม่มีคุณสมบัติ อย่างมีประสิทธิภาพ สิ่งนี้จะป้องกันคุณสมบัติไดนามิกในขณะที่ยังคงอนุญาตให้คลาสย่อยประกาศคุณสมบัติแบบ readonly
อย่างเดียวได้อย่างชัดเจน
ถัดไป คลาสแบบ readonly
อย่างเดียวสามารถมีได้เฉพาะคุณสมบัติที่พิมพ์ — กฎเดียวกันสำหรับการประกาศคุณสมบัติ อ่าน อย่างเดียวแต่ละรายการ
คุณสามารถใช้คุณสมบัติชนิด mixed
ได้ หากคุณไม่สามารถประกาศคุณสมบัติที่พิมพ์อย่างเคร่งครัด
การพยายามประกาศคลาสแบบ readonly
อย่างเดียวโดยไม่มีคุณสมบัติที่พิมพ์จะส่งผลให้เกิดข้อผิดพลาดร้ายแรง:
readonly class Type { public $nope; } Fatal error: Readonly property Type::$nope must have type in ... on line ...
นอกจากนี้ คุณไม่สามารถประกาศคุณสมบัติ PHP แบบ readonly
อย่างเดียวได้:
- Enums (เนื่องจากไม่มีคุณสมบัติใด ๆ )
- ลักษณะนิสัย
- อินเทอร์เฟซ
การพยายามประกาศคุณลักษณะใดๆ เหล่านี้เป็นแบบ readonly
อย่างเดียวจะส่งผลให้เกิดข้อผิดพลาดในการแยกวิเคราะห์
readonly interface Destiny {} Parse error: syntax error, unexpected token "interface", expecting "abstract" or "final" or "readonly" or "class" in ... on line ...
เช่นเดียวกับคีย์เวิร์ด PHP ทั้งหมด คีย์เวิร์ดแบบ readonly
อย่างเดียวไม่คำนึงถึงขนาดตัวพิมพ์
PHP 8.2 ยังเลิกใช้คุณสมบัติไดนามิก (เพิ่มเติมในภายหลัง) แต่คุณไม่สามารถป้องกันคุณสมบัติไดนามิกไม่ให้ถูกเพิ่มในคลาสได้ อย่างไรก็ตาม การทำเช่นนี้สำหรับคลาสแบบ readonly
อย่างเดียวจะส่งผลให้เกิดข้อผิดพลาดร้ายแรงเท่านั้น
Fatal error: Readonly property Test::$test must have type in ... on line ...
อนุญาต true
, false
และ null
เป็น Standalone Types
PHP มีประเภทสเกลาร์อยู่แล้ว เช่น int
, string
และ bool
ที่ได้รับการขยายใน PHP 8.0 ด้วยการเพิ่มประเภทยูเนี่ยนทำให้ค่าเป็นประเภทต่างๆ RFC เดียวกันยังอนุญาตให้ใช้ false
และ null
เป็นส่วนหนึ่งของประเภทยูเนี่ยน - แม้ว่าจะไม่ได้รับอนุญาตให้เป็นแบบสแตนด์อโลนก็ตาม
หากคุณพยายามประกาศ false
หรือเป็น null
หรือเป็นประเภทสแตนด์อโลน — โดยไม่ได้เป็นส่วนหนึ่งของประเภทสหภาพ — จะส่งผลให้เกิดข้อผิดพลาดร้ายแรง
function spam(): null {} function eggs(): false {} Fatal error: Null can not be used as a standalone type in ... on line ... Fatal error: False can not be used as a standalone type in ... on line ...
เพื่อหลีกเลี่ยงสถานการณ์นี้ PHP 8.2 ได้เพิ่มการสนับสนุนสำหรับการใช้ false
และ null
เป็นประเภทสแตนด์อโลน ด้วยการเพิ่มนี้ ระบบประเภทของ PHP จึงมีความชัดเจนและสมบูรณ์ยิ่งขึ้น ขณะนี้คุณสามารถประกาศประเภทการส่งคืน พารามิเตอร์ และคุณสมบัติได้อย่างแม่นยำ
นอกจากนี้ PHP ยังไม่รวมประเภท true
ซึ่งดูเหมือนว่าจะเป็นประเภทที่คล้ายคลึงกันโดยธรรมชาติของประเภท false
PHP 8.2 แก้ไขและเพิ่มการรองรับสำหรับประเภท true
เช่นกัน ไม่อนุญาตให้บังคับ เหมือนกับพฤติกรรมของประเภท false
ทั้งประเภท true
และ false
นั้นเป็นประเภท bool
ลของ PHP แบบยูเนียน เพื่อหลีกเลี่ยงความซ้ำซ้อน คุณไม่สามารถประกาศสามประเภทนี้ร่วมกันในประเภทสหภาพ การทำเช่นนี้จะส่งผลให้เกิดข้อผิดพลาดร้ายแรงในการคอมไพล์
Disjunctive Normal Form (DNF) ประเภท
Disjunctive Normal Form (DNF) เป็นวิธีมาตรฐานในการจัดระเบียบนิพจน์บูลีน ประกอบด้วยการแยกคำสันธาน — ในแง่บูลีน นั่นคือ OR ของ ANDs
การใช้ DNF กับการประกาศประเภทช่วยให้มีวิธีมาตรฐานในการเขียนประเภท Union และ Intersection ที่ Parser สามารถจัดการได้ คุณสมบัติประเภท DNF ใหม่ของ PHP 8.2 นั้นเรียบง่ายแต่ทรงพลังหากใช้อย่างเหมาะสม
RFC ให้ตัวอย่างต่อไปนี้ ถือว่าอินเทอร์เฟซและคำจำกัดความคลาสต่อไปนี้มีอยู่แล้ว:
interface A {} interface B {} interface C extends A {} interface D {} class W implements A {} class X implements B {} class Y implements A, B {} class Z extends Y implements C {}
ด้วยประเภท DNF คุณสามารถดำเนินการประกาศประเภทสำหรับคุณสมบัติ พารามิเตอร์ และค่าที่ส่งคืนได้ดังนี้:
// Accepts an object that implements both A and B, // OR an object that implements D (A&B)|D // Accepts an object that implements C, // OR a child of X that also implements D, // OR null C|(X&D)|null // Accepts an object that implements all three of A, B, and D, // OR an int, // OR null. (A&B&D)|int|null
ในบางกรณี คุณสมบัติอาจไม่อยู่ในรูปแบบ DNF การประกาศเช่นนั้นจะส่งผลให้เกิดข้อผิดพลาดในการแยกวิเคราะห์ แต่คุณสามารถเขียนใหม่เป็น:
A&(B|D) // Can be rewritten as (A&B)|(A&D) A|(B&(D|W)|null) // Can be rewritten as A|(B&D)|(B&W)|null
คุณควรทราบว่าแต่ละส่วนของประเภท DNF ต้องไม่ซ้ำกัน ตัวอย่างเช่น การประกาศ (A&B)|(B&A)
ไม่ถูกต้อง เนื่องจากส่วน OR ed สองส่วนนั้นมีเหตุผลเหมือนกัน
นอกจากนี้ ยังไม่อนุญาตให้ใช้กลุ่มที่เป็นชุดย่อยที่เข้มงวดของอีกกลุ่มหนึ่ง นั่นเป็นเพราะว่า superset จะมีอินสแตนซ์ทั้งหมดของเซ็ตย่อยอยู่แล้ว ซึ่งทำให้ซ้ำซ้อนกับการใช้ DNF
แก้ไขพารามิเตอร์ที่ละเอียดอ่อนในการติดตามย้อนกลับ
เช่นเดียวกับภาษาการเขียนโปรแกรมเกือบทุกภาษา PHP อนุญาตให้ติดตาม call stack ได้ทุกจุดในการดำเนินการของโค้ด การติดตามสแต็กทำให้ง่ายต่อการดีบักโค้ดเพื่อแก้ไขข้อผิดพลาดและคอขวดด้านประสิทธิภาพ เป็นแกนหลักของเครื่องมืออย่าง Kinsta APM ซึ่งเป็นเครื่องมือตรวจสอบประสิทธิภาพที่ออกแบบเองของเราสำหรับไซต์ WordPress
การดำเนินการติดตามสแต็กไม่ได้หยุดการทำงานของโปรแกรม โดยปกติ สแต็กเทรซส่วนใหญ่จะทำงานในเบื้องหลังและถูกบันทึกโดยไม่โต้ตอบ — สำหรับการตรวจสอบในภายหลังหากจำเป็น
อย่างไรก็ตาม สแต็กเทรซ PHP ที่มีรายละเอียดบางส่วนอาจเป็นข้อเสียหากคุณแชร์กับบริการของบุคคลที่สาม โดยปกติสำหรับการวิเคราะห์บันทึกข้อผิดพลาด การติดตามข้อผิดพลาด ฯลฯ สแต็กเทรซเหล่านี้อาจมีข้อมูลที่ละเอียดอ่อน เช่น ชื่อผู้ใช้ รหัสผ่าน และตัวแปรสภาพแวดล้อม .
ข้อเสนอ RFC นี้ให้ตัวอย่างหนึ่งตัวอย่าง:
"ผู้กระทำความผิด" ทั่วไปอย่างหนึ่งคือ PDO ซึ่งใช้รหัสผ่านฐานข้อมูลเป็นพารามิเตอร์ตัวสร้างและพยายามเชื่อมต่อกับฐานข้อมูลภายในตัวสร้างทันที แทนที่จะมีตัวสร้างบริสุทธิ์และเมธอด ->connect() แยกต่างหาก ดังนั้นเมื่อการเชื่อมต่อฐานข้อมูลล้มเหลว การติดตามสแต็กจะรวมรหัสผ่านฐานข้อมูล:
PDOException: SQLSTATE[HY000] [2002] No such file or directory in /var/www/html/test.php:3 Stack trace: #0 /var/www/html/test.php(3): PDO->__construct('mysql:host=loca...', 'root', 'password') #1 {main}
PHP 8.2 ช่วยให้คุณสามารถทำเครื่องหมายพารามิเตอร์ที่ละเอียดอ่อนดังกล่าวด้วยแอตทริบิวต์ \SensitiveParameter
ใหม่ พารามิเตอร์ใด ๆ ที่ทำเครื่องหมายว่าละเอียดอ่อนจะไม่อยู่ในรายการย้อนหลังของคุณ ดังนั้น คุณสามารถแบ่งปันได้โดยไม่ต้องกังวลกับบริการของบุคคลที่สาม
ต่อไปนี้คือตัวอย่างที่ตรงไปตรงมาพร้อมพารามิเตอร์ที่ละเอียดอ่อนเพียงตัวเดียว:
<?php function example( $ham, #[\SensitiveParameter] $eggs, $butter ) { throw new \Exception('Error'); } example('ham', 'eggs', 'butter'); /* Fatal error: Uncaught Exception: Error in test.php:8 Stack trace: #0 test.php(11): test('ham', Object(SensitiveParameterValue), 'butter') #1 {main} thrown in test.php on line 8 */
เมื่อคุณสร้าง backtrace พารามิเตอร์ใดๆ ที่มีแอตทริบิวต์ \SensitiveParameter
จะถูกแทนที่ด้วยอ็อบเจ็กต์ \SensitiveParameterValue
และค่าจริงของพารามิเตอร์จะไม่ถูกเก็บไว้ในการติดตาม ออบเจ็กต์ SensitiveParameterValue
สรุปค่าพารามิเตอร์จริง — หากคุณต้องการด้วยเหตุผลใดก็ตาม
ฟังก์ชัน mysqli_execute_query
ใหม่และ mysqli::execute_query
Method
คุณเคยใช้ฟังก์ชัน mysqli_query()
ที่มีการหลีกเลี่ยงค่าผู้ใช้อย่างอันตรายเพียงเพื่อเรียกใช้แบบสอบถาม MySQLi แบบกำหนดพารามิเตอร์หรือไม่?
PHP 8.2 ทำให้การสืบค้น MySQLi แบบกำหนดพารามิเตอร์ทำได้ง่ายขึ้นด้วย mysqli_execute_query($sql, $params)
ใหม่และวิธี mysqli::execute_query
โดยพื้นฐานแล้ว ฟังก์ชันใหม่นี้คือการรวมกันของ mysqli_prepare()
, mysqli_execute()
และ mysqli_stmt_get_result()
ด้วยวิธีนี้ แบบสอบถาม MySQLi จะถูกจัดเตรียม ผูกไว้ (หากคุณส่งผ่านพารามิเตอร์ใดๆ ก็ตาม) และดำเนินการภายในฟังก์ชันเอง หากการสืบค้นทำงานสำเร็จ มันจะส่งคืนวัตถุ mysqli_result
หากไม่สำเร็จ มันจะคืนค่า false
ข้อเสนอ RFC ให้ตัวอย่างที่เรียบง่ายแต่ทรงพลัง:
foreach ($db->execute_query('SELECT * FROM user WHERE name LIKE ? AND type_id IN (?, ?)', [$name, $type1, $type2]) as $row) { print_r($row); }
ดึงคุณสมบัติ enum
ใน const
Expressions
RFC นี้เสนอให้ตัวดำเนินการ ->/?->
ดึงคุณสมบัติ enum
ในนิพจน์ const
เหตุผลหลักสำหรับคุณลักษณะใหม่นี้คือ คุณไม่สามารถใช้วัตถุ enum
ในบางที่ เช่น คีย์อาร์เรย์ ในกรณีเช่นนี้ คุณจะต้องทำซ้ำค่าของกรณี enum
เพื่อใช้งาน
การอนุญาตให้ดึงคุณสมบัติ enum
ในสถานที่ที่ไม่อนุญาตให้ใช้วัตถุ enum
สามารถทำให้ขั้นตอนนี้ง่ายขึ้น
หมายความว่ารหัสต่อไปนี้ใช้ได้แล้ว:
const C = [self::B->value => self::B];
และเพื่อความปลอดภัย RFC นี้ยังรองรับตัวดำเนินการ nullsafe ?->
อนุญาตค่าคงที่ในลักษณะ
PHP มีวิธีการนำโค้ดกลับมาใช้ใหม่ที่เรียกว่า Traits เหมาะอย่างยิ่งสำหรับการใช้รหัสซ้ำในชั้นเรียนต่างๆ
ปัจจุบัน Traits อนุญาตให้กำหนดวิธีการและคุณสมบัติเท่านั้น แต่ไม่สามารถใช้ค่าคงที่ได้ นั่นหมายความว่าคุณไม่สามารถกำหนดค่าคงที่ที่คาดไว้โดยลักษณะภายในลักษณะเอง เพื่อหลีกเลี่ยงข้อจำกัดนี้ คุณต้องกำหนดค่าคงที่ในคลาสการเขียนหรืออินเทอร์เฟซที่ดำเนินการโดยคลาสการเขียน
RFC นี้เสนอให้กำหนดค่าคงที่ในลักษณะ ค่าคงที่เหล่านี้สามารถกำหนดได้เหมือนกับที่คุณกำหนดค่าคงที่ของคลาส ตัวอย่างนี้นำมาจาก RFC โดยตรงเพื่อล้างอากาศโดยรอบการใช้งาน:
trait Foo { public const FLAG_1 = 1; protected const FLAG_2 = 2; private const FLAG_3 = 2; public function doFoo(int $flags): void { if ($flags & self::FLAG_1) { echo 'Got flag 1'; } if ($flags & self::FLAG_2) { echo 'Got flag 2'; } if ($flags & self::FLAG_3) { echo 'Got flag 3'; } } }
ค่าคงที่ของ Trait จะถูกรวมเข้ากับนิยามของคลาสการเรียบเรียง เช่นเดียวกับนิยามคุณสมบัติและเมธอดของ Trait พวกเขายังมีข้อจำกัดที่คล้ายคลึงกันเป็นคุณสมบัติของคุณลักษณะ ตามที่ระบุไว้ใน RFC ข้อเสนอนี้แม้ว่าจะเป็นการเริ่มต้นที่ดีก็ตาม แต่จำเป็นต้องดำเนินการเพิ่มเติมเพื่อพัฒนาคุณลักษณะนี้
การเลิกใช้งานใน PHP 8.2
ตอนนี้ เราสามารถย้ายไปสำรวจการเลิกใช้งานทั้งหมดใน PHP 8.2 ได้แล้ว รายการนี้ไม่ใหญ่เท่ากับคุณสมบัติใหม่:
เลิกใช้คุณสมบัติไดนามิก (และแอตทริบิวต์ #[AllowDynamicProperties]
ใหม่)
จนถึง PHP 8.1 คุณสามารถตั้งค่าและเรียกคุณสมบัติของคลาสที่ไม่ได้ประกาศใน PHP แบบไดนามิกได้ ตัวอย่างเช่น:
class Post { private int $pid; } $post = new Post(); $post->name = 'Kinsta';
ที่นี่ คลาส Post
ไม่ได้ประกาศคุณสมบัติ name
แต่เนื่องจาก PHP อนุญาตคุณสมบัติไดนามิก คุณจึงสามารถตั้งค่าภายนอกการประกาศคลาสได้ นั่นเป็นข้อได้เปรียบที่ใหญ่ที่สุดและอาจเป็นข้อได้เปรียบเพียงอย่างเดียว
คุณสมบัติไดนามิกช่วยให้เกิดข้อบกพร่องและพฤติกรรมที่ไม่คาดคิดในโค้ดของคุณ ตัวอย่างเช่น หากคุณทำผิดพลาดขณะประกาศคุณสมบัติของคลาสนอกคลาส การติดตามคุณสมบัตินั้นทำได้ง่ายโดยเฉพาะอย่างยิ่งเมื่อทำการดีบั๊กข้อผิดพลาดภายในคลาสนั้น
ตั้งแต่ PHP 8.2 เป็นต้นไป คุณสมบัติไดนามิกจะถูกเลิกใช้ การตั้งค่าคุณสมบัติคลาสที่ไม่ได้ประกาศจะส่งการแจ้งเตือนการเลิกใช้งานในครั้งแรกที่มีการตั้งค่าคุณสมบัติ
class Foo {} $foo = new Foo; // Deprecated: Creation of dynamic property Foo::$bar is deprecated $foo->bar = 1; // No deprecation warning: Dynamic property already exists. $foo->bar = 2;
อย่างไรก็ตาม ตั้งแต่ PHP 9.0 เป็นต้นไป การตั้งค่าแบบเดียวกันจะทำให้เกิดข้อผิดพลาด ErrorException
หากโค้ดของคุณเต็มไปด้วยคุณสมบัติไดนามิก — และมีโค้ด PHP จำนวนมาก — และหากคุณต้องการหยุดประกาศการเลิกใช้งานเหล่านี้หลังจากอัปเกรดเป็น PHP 8.2 คุณสามารถใช้แอตทริบิวต์ #[AllowDynamicProperties]
ใหม่ของ PHP 8.2 เพื่ออนุญาตไดนามิก คุณสมบัติในชั้นเรียน
#[AllowDynamicProperties] class Pets {} class Cats extends Pets {} // You'll get no deprecation warning $obj = new Pets; $obj->test = 1; // You'll get no deprecation warning for child classes $obj = new Cats; $obj->test = 1;
ตาม RFC คลาสที่ทำเครื่องหมายเป็น #[AllowDynamicProperties]
เช่นเดียวกับคลาสย่อย สามารถใช้คุณสมบัติไดนามิกต่อไปได้โดยไม่ต้องเลิกใช้งานหรือลบออก
คุณควรทราบด้วยว่าใน PHP 8.2 คลาสบันเดิลเดียวที่ทำเครื่องหมายว่า #[AllowDynamicProperties]
คือ stdClass
นอกจากนี้ คุณสมบัติใดๆ ที่เข้าถึงผ่าน __get()
หรือ __set()
PHP จะไม่ถือเป็นคุณสมบัติไดนามิก เพื่อไม่ให้มีการแจ้งการเลิกใช้งาน
เลิกใช้งาน Callables ที่รองรับบางส่วน
การเปลี่ยนแปลง PHP 8.2 อีกประการหนึ่ง แม้ว่าจะมีผลกระทบเพียงเล็กน้อยเท่านั้น คือการเลิกใช้งาน callables ที่รองรับได้บางส่วน
เรียกได้เหล่านี้เรียกว่าสนับสนุนบางส่วนเนื่องจากคุณไม่สามารถโต้ตอบกับพวกเขาโดยตรงผ่าน $callable()
คุณสามารถเข้าถึงได้โดยใช้ฟังก์ชัน call_user_func($callable)
เท่านั้น รายการของ callables ดังกล่าวไม่นาน:
"self::method" "parent::method" "static::method" ["self", "method"] ["parent", "method"] ["static", "method"] ["Foo", "Bar::method"] [new Foo, "Bar::method"]
ตั้งแต่ PHP 8.2 เป็นต้นไป ความพยายามใดๆ ในการเรียกใช้ callables ดังกล่าว เช่น ผ่านฟังก์ชัน call_user_func()
หรือ array_map()
จะส่งคำเตือนการเลิกใช้งาน
RFC ดั้งเดิมให้เหตุผลที่มั่นคงเบื้องหลังการเลิกใช้งานนี้:
นอกเหนือจากสองกรณีสุดท้าย callables เหล่านี้ทั้งหมดขึ้นอยู่กับบริบท วิธีการที่
"self::method"
อ้างอิงขึ้นอยู่กับคลาสที่เรียกใช้หรือการตรวจสอบความสามารถในการเรียก ในทางปฏิบัติ มักใช้กับสองกรณีสุดท้ายเมื่อใช้ในรูปแบบของ[new Foo, "parent::method"]
การลดการพึ่งพาบริบทของ callables เป็นเป้าหมายรองของ RFC นี้ หลังจาก RFC นี้ การพึ่งพาขอบเขตเพียงอย่างเดียวที่ยังคงอยู่คือการมองเห็นเมธอด:
"Foo::bar"
อาจมองเห็นได้ในขอบเขตหนึ่ง แต่ไม่ใช่อีกขอบเขตหนึ่ง หาก callables ถูก จำกัด ไว้ที่วิธีการสาธารณะในอนาคต (ในขณะที่เมธอดส่วนตัวจะต้องใช้ callables ระดับเฟิร์สคลาสหรือClosure::fromCallable()
เพื่อให้ไม่มีขอบเขต) ดังนั้นประเภทที่เรียกได้จะมีความชัดเจนและสามารถ ใช้เป็นประเภททรัพย์สิน อย่างไรก็ตาม การเปลี่ยนแปลงในการจัดการการมองเห็นจะไม่ถูกเสนอให้เป็นส่วนหนึ่งของ RFC นี้
ตาม RFC ดั้งเดิม ฟังก์ชัน is_callable()
และประเภท callable
จะยังคงยอมรับ callable เหล่านี้เป็นข้อยกเว้น แต่จนกว่าการสนับสนุนจะถูกลบออกจาก PHP 9.0 เป็นต้นไปทั้งหมด
เพื่อหลีกเลี่ยงความสับสน ขอบเขตการแจ้งการเลิกใช้งานนี้จึงถูกขยายด้วย RFC ใหม่ ซึ่งขณะนี้ได้รวมข้อยกเว้นเหล่านี้ไว้ด้วย
เป็นเรื่องดีที่ได้เห็น PHP ก้าวไปสู่การมีประเภท callable
ที่กำหนดไว้อย่างดี
เลิกใช้ฟังก์ชัน #utf8_encode()
และ utf8_decode()
ฟังก์ชันในตัวของ PHP utf8_encode()
และ utf8_decode()
แปลงสตริงที่เข้ารหัสใน ISO-8859-1 (“Latin 1”) เป็นและจาก UTF-8
อย่างไรก็ตาม ชื่อของพวกเขาแนะนำการใช้งานทั่วไปมากกว่าการนำไปใช้ การเข้ารหัส "Latin 1" มักสับสนกับการเข้ารหัสอื่นๆ เช่น "Windows Code Page 1252"
นอกจากนี้ คุณมักจะเห็น Mojibake เมื่อฟังก์ชันเหล่านี้ไม่สามารถแปลงสตริงได้อย่างถูกต้อง การไม่มีข้อความแสดงข้อผิดพลาดยังหมายความว่าจะมองเห็นได้ยาก โดยเฉพาะอย่างยิ่งภายในทะเลที่มีข้อความที่อ่านออกได้ชัดเจน
PHP 8.2 เลิกใช้ทั้งฟังก์ชัน #utf8_encode()
และ utf8_decode()
หากคุณเรียกใช้ คุณจะเห็นประกาศการเลิกใช้งานเหล่านี้:
Deprecated: Function utf8_encode() is deprecated Deprecated: Function utf8_decode() is deprecated
RFC แนะนำให้ใช้ส่วนขยายที่รองรับของ PHP เช่น mbstring
, iconv
และ intl
แทน
เลิกใช้ ${}
String Interpolation
PHP อนุญาตให้ฝังตัวแปรในสตริงที่มีเครื่องหมายคำพูดคู่ ( "
) และ heredoc ( <<<
) ได้หลายวิธี:
- การฝังตัวแปรโดยตรง —
“$foo”
- ด้วยวงเล็บปีกกานอกตัวแปร —
“{$foo}”
- ด้วยเครื่องหมายวงเล็บหลังเครื่องหมายดอลลาร์ —
“${foo}”
- ตัวแปรตัวแปร —
“${expr}”
— เทียบเท่ากับการใช้(string) ${expr}
สองวิธีแรกมีข้อดีและข้อเสีย ในขณะที่สองวิธีแรกมีไวยากรณ์ที่ซับซ้อนและขัดแย้งกัน PHP 8.2 เลิกใช้สองวิธีสุดท้ายของการแก้ไขสตริง
คุณควรหลีกเลี่ยงการสอดแทรกสตริงด้วยวิธีนี้:
"Hello, ${world}!"; Deprecated: Using ${} in strings is deprecated "Hello, ${(world)}!"; Deprecated: Using ${} (variable variables) in strings is deprecated
เริ่มต้นด้วย PHP 9.0 การเลิกใช้งานเหล่านี้จะได้รับการอัปเกรดเพื่อให้เกิดข้อผิดพลาดในการยกเว้น
เลิกใช้ฟังก์ชัน mbstring สำหรับเอนทิตี Base64/QPrint/Uuencode/HTML
ฟังก์ชัน mbstring (สตริงแบบหลายไบต์) ของ PHP ช่วยให้เราทำงานกับ Unicode, เอนทิตี HTML และการเข้ารหัสข้อความแบบเดิมอื่นๆ
อย่างไรก็ตาม Base64, Uuencode และ QPrint ไม่ใช่การเข้ารหัสข้อความและยังคงเป็นส่วนหนึ่งของฟังก์ชันเหล่านี้ สาเหตุหลักมาจากเหตุผลเดิม PHP ยังรวมการใช้งานการเข้ารหัสเหล่านี้แยกต่างหาก
สำหรับเอนทิตี HTML นั้น PHP มีฟังก์ชันในตัว — htmlspecialchars()
และ htmlentities()
— เพื่อจัดการกับสิ่งเหล่านี้ได้ดียิ่งขึ้น ตัวอย่างเช่น ไม่เหมือนกับ mbstring ฟังก์ชันเหล่านี้จะแปลง <
>
, และ &
อักขระสำหรับเอนทิตี HTML
นอกจากนี้ PHP ยังปรับปรุงฟังก์ชันในตัวอยู่เสมอ เช่นเดียวกับ PHP 8.1 ที่มีฟังก์ชันการเข้ารหัสและถอดรหัส HTML
ดังนั้น เมื่อคำนึงถึงสิ่งนั้น PHP 8.2 กำลังเลิกใช้ mbstring สำหรับการเข้ารหัสเหล่านี้ (ป้ายกำกับไม่คำนึงถึงขนาดตัวพิมพ์):
- BASE64
- ยูเอ็นโค้ด
- HTML-ENTITIES
- html (นามแฝงของ HTML-ENTITIES)
- อ้าง-พิมพ์ได้
- qprint (นามแฝงของ Quoted-Printable)
ตั้งแต่ PHP 8.2 เป็นต้นไป การใช้ mbstring เพื่อเข้ารหัส/ถอดรหัสข้อใดข้อหนึ่งข้างต้น จะเป็นการส่งการแจ้งเตือนการเลิกใช้งาน PHP 9.0 จะลบการสนับสนุน mbstring สำหรับการเข้ารหัสเหล่านี้ทั้งหมด
การเปลี่ยนแปลงเล็กน้อยอื่นๆ ใน PHP 8.2
สุดท้ายนี้ เราสามารถพูดคุยเกี่ยวกับการเปลี่ยนแปลงเล็กน้อยของ PHP 8.2 รวมถึงคุณลักษณะและฟังก์ชันที่ถูกลบออกไป
ลบการสนับสนุนสำหรับ libmysql จาก mysqli
ณ ตอนนี้ PHP อนุญาตให้ทั้งไดรเวอร์ mysqli
และ PDO_mysql
สร้างขึ้นจาก mysqlnd
และ libmysql
อย่างไรก็ตาม ค่าเริ่มต้นและไดรเวอร์ที่แนะนำตั้งแต่ PHP 5.4 คือ mysqlnd
ไดรเวอร์ทั้งสองนี้มีข้อดีและข้อเสียมากมาย อย่างไรก็ตาม การยกเลิกการสนับสนุนสำหรับหนึ่งในนั้น — เป็นการดีที่การลบ libmysql
เนื่องจากไม่ใช่ค่าเริ่มต้น — จะทำให้การทดสอบโค้ดและหน่วยของ PHP ง่ายขึ้น
เพื่อสร้างข้อโต้แย้งสำหรับความโปรดปรานนี้ RFC แสดงรายการข้อดีมากมายของ mysqlnd
:
- มันมาพร้อมกับ PHP
- ใช้การจัดการหน่วยความจำ PHP เพื่อตรวจสอบการใช้หน่วยความจำและ
ปรับปรุงประสิทธิภาพ - ให้ฟังก์ชันคุณภาพชีวิต (เช่น
get_result()
) - ส่งกลับค่าตัวเลขโดยใช้ PHP native types
- ฟังก์ชันการทำงานไม่ได้ขึ้นอยู่กับไลบรารีภายนอก
- ฟังก์ชั่นปลั๊กอินเสริม
- รองรับการสืบค้นข้อมูลแบบอะซิงโครนัส
RFC ยังแสดงรายการข้อดีของ libmysql
ซึ่งรวมถึง:
- สามารถเชื่อมต่อใหม่อัตโนมัติได้ (
mysqlnd
ไม่สนับสนุนฟังก์ชันนี้โดยเจตนาเพราะสามารถใช้ประโยชน์ได้ง่าย) - โหมดการพิสูจน์ตัวตน LDAP และ SASL (
mysqlnd
อาจเพิ่มคุณสมบัตินี้เร็ว ๆ นี้ด้วย)
นอกจากนี้ RFC ยังระบุข้อเสียหลายประการของ libmysql
— ความเข้ากันไม่ได้กับโมเดลหน่วยความจำ PHP, การทดสอบที่ล้มเหลวจำนวนมาก, หน่วยความจำรั่ว, ฟังก์ชันการทำงานที่แตกต่างกันระหว่างเวอร์ชัน ฯลฯ
เมื่อคำนึงถึงทั้งหมดนี้ PHP 8.2 ได้ลบการสนับสนุนสำหรับการสร้าง mysqli
เทียบกับ libmysql
หากคุณต้องการเพิ่มฟังก์ชันใดๆ ที่มีให้เฉพาะกับ libmysql
คุณจะต้องเพิ่มฟังก์ชันดังกล่าวใน mysqlnd
อย่างชัดเจนเพื่อขอคุณสมบัติ นอกจากนี้ คุณไม่สามารถเพิ่มการเชื่อมต่อใหม่อัตโนมัติได้
การแปลงตัวพิมพ์ที่ไม่ขึ้นกับสถานที่
ก่อน PHP 8.0 โลแคลของ PHP นั้นสืบทอดมาจากสภาพแวดล้อมของระบบ แต่สิ่งนี้อาจทำให้เกิดปัญหาได้ในบางกรณี
การตั้งค่าภาษาของคุณขณะติดตั้ง Linux จะตั้งค่าภาษาอินเทอร์เฟซผู้ใช้ที่เหมาะสมสำหรับคำสั่งในตัว อย่างไรก็ตาม ยังเปลี่ยนวิธีการทำงานของการจัดการสตริงของไลบรารี C โดยไม่คาดคิดอีกด้วย
ตัวอย่างเช่น หากคุณเลือกภาษา “ตุรกี” หรือ “คาซัค” เมื่อติดตั้ง Linux คุณจะพบว่าการเรียก toupper('i')
เพื่อให้ได้ตัวพิมพ์ใหญ่เทียบเท่าจะได้ตัวพิมพ์ใหญ่ประ I (U+0130, I
)
PHP 8.0 หยุดความผิดปกตินี้ด้วยการตั้งค่าสถานที่เริ่มต้นเป็น “C” เว้นแต่ผู้ใช้จะเปลี่ยนแปลงอย่างชัดเจนผ่าน setlocale()
PHP 8.2 ก้าวไปอีกขั้นด้วยการลบความไวของสถานที่ออกจากการแปลงตัวพิมพ์ RFC นี้ส่วนใหญ่เปลี่ยนแปลง strtolower()
, strtoupper( strtoupper()
และฟังก์ชันที่เกี่ยวข้อง อ่าน RFC เพื่อดูรายการฟังก์ชันที่ได้รับผลกระทบทั้งหมด
อีกทางเลือกหนึ่ง หากคุณต้องการใช้การแปลงตัวพิมพ์ที่แปลแล้ว คุณสามารถใช้ mb_strtolower()
การปรับปรุงส่วนขยายแบบสุ่ม
PHP กำลังวางแผนที่จะยกเครื่องฟังก์ชันการทำงานแบบสุ่ม
ณ ตอนนี้ ฟังก์ชันสุ่มของ PHP นั้นอาศัยสถานะ Mersenne Twister เป็นอย่างมาก อย่างไรก็ตาม สถานะนี้ถูกจัดเก็บโดยปริยายในพื้นที่ส่วนกลางของ PHP ไม่มีทางที่ผู้ใช้จะสามารถเข้าถึงได้ การเพิ่มฟังก์ชันการสุ่มระหว่างขั้นตอนการเพาะเริ่มต้นและการใช้งานที่ตั้งใจไว้จะทำให้โค้ดเสียหาย
การรักษารหัสดังกล่าวอาจซับซ้อนยิ่งขึ้นเมื่อรหัสของคุณใช้แพ็คเกจภายนอก
ดังนั้น ฟังก์ชันการสุ่มในปัจจุบันของ PHP ไม่สามารถสร้างค่าสุ่มได้อย่างสม่ำเสมอ มันยังล้มเหลวในการทดสอบทางสถิติเชิงประจักษ์ของเครื่องกำเนิดตัวเลขสุ่มแบบเดียวกัน เช่น Crush และ BigCrush ของ TestU01 ข้อจำกัด 32 บิตของ Mersenne Twister ยิ่งทำให้รุนแรงขึ้น
ดังนั้น จึงไม่แนะนำให้ใช้ฟังก์ชันในตัวของ PHP — shuffle()
, str_shuffle()
, array_rand()
— หากคุณต้องการตัวเลขสุ่มที่ปลอดภัยในการเข้ารหัส ในกรณีดังกล่าว คุณจะต้องใช้ฟังก์ชันใหม่โดยใช้ random_int()
หรือฟังก์ชันที่คล้ายกัน
อย่างไรก็ตาม หลายประเด็นเกี่ยวกับ RFC นี้ถูกหยิบยกขึ้นมาหลังจากเริ่มลงคะแนนเสียงแล้ว ความล้มเหลวนี้ทำให้ทีม PHP ต้องจดบันทึกปัญหาทั้งหมดใน RFC ที่แยกจากกัน โดยมีตัวเลือกการลงคะแนนเสียงที่สร้างขึ้นสำหรับแต่ละประเด็น พวกเขาจะตัดสินใจเดินหน้าต่อไปหลังจากบรรลุข้อตกลงร่วมกันเท่านั้น
RFC เพิ่มเติมใน PHP 8.2
PHP 8.2 ยังมีฟังก์ชันใหม่มากมายและการเปลี่ยนแปลงเล็กน้อย เราจะกล่าวถึงด้านล่างพร้อมลิงก์ไปยังแหล่งข้อมูลเพิ่มเติม:
- ฟังก์ชัน
curl_upkeep
ใหม่: PHP 8.2 เพิ่มฟังก์ชันใหม่นี้ให้กับส่วนขยาย Curl มันเรียกcurl_easy_upkeep()
ใน libcurl ซึ่งเป็นไลบรารี C พื้นฐานที่ส่วนขยาย PHP Curl ใช้ - ฟังก์ชัน
ini_parse_quantity
ใหม่: คำสั่ง PHP INI ยอมรับขนาดข้อมูลที่มีส่วนต่อท้ายตัวคูณ ตัวอย่างเช่น คุณสามารถเขียน 25 เมกะไบต์เป็น25M
หรือ 42 กิกะไบต์เป็นเพียง42G
คำต่อท้ายเหล่านี้พบได้ทั่วไปในไฟล์ PHP INI แต่พบไม่บ่อยในที่อื่นๆ ฟังก์ชันใหม่นี้จะวิเคราะห์ค่า PHP INI และส่งกลับขนาดข้อมูลเป็นไบต์ - ฟังก์ชัน
memory_reset_peak_usage
ใหม่: ฟังก์ชันนี้จะรีเซ็ตการใช้หน่วยความจำสูงสุดที่ส่งคืนโดยฟังก์ชันmemory_get_peak_usage
อาจมีประโยชน์เมื่อคุณใช้งานการกระทำเดียวกันหลายครั้งและต้องการบันทึกการใช้หน่วยความจำสูงสุดของการวิ่งแต่ละครั้ง - รองรับโมดิฟายเออร์ที่ไม่มีการจับภาพ (
/n
) ในฟังก์ชันpreg_*
: ใน regex อักขระเมตา()
จะระบุกลุ่มการดักจับ นั่นหมายความว่าผลลัพธ์ที่ตรงกันทั้งหมดสำหรับนิพจน์ภายในวงเล็บจะถูกส่งกลับ PHP 8.2 เพิ่มตัวแก้ไขที่ไม่มีการจับภาพ (/n
) เพื่อหยุดการทำงานนี้ - ทำให้ตระกูล
iterator_*()
ยอมรับ iterables ทั้งหมด: ณ ตอนนี้ ตระกูลiterator_*()
_*() ของ PHP ยอมรับเฉพาะ\Traversables
(เช่น ไม่อนุญาตให้ใช้อาร์เรย์ธรรมดา) เป็นการจำกัดโดยไม่จำเป็น และ RFC นี้แก้ไขได้
สรุป
PHP 8.2 สร้างขึ้นจากการปรับปรุงครั้งใหญ่ใน PHP 8.0 และ PHP 8.1 ซึ่งไม่ใช่เรื่องง่าย เราคิดว่าคุณสมบัติ PHP 8.2 ที่น่าตื่นเต้นที่สุดคือประเภทสแตนด์อโลนใหม่ คุณสมบัติแบบอ่านอย่างเดียว และการปรับปรุงประสิทธิภาพมากมาย
เราไม่สามารถรอที่จะเปรียบเทียบ PHP 8.2 กับเฟรมเวิร์ก PHP และ CMS ต่างๆ ได้
อย่าลืมบุ๊กมาร์กโพสต์ในบล็อกนี้เพื่อใช้อ้างอิงในอนาคต
คุณสมบัติ PHP 8.2 ใดที่คุณชื่นชอบ? การเลิกใช้งานใดที่คุณชอบน้อยที่สุด กรุณาแบ่งปันความคิดของคุณกับชุมชนของเราในความคิดเห็น!