Sự khác biệt giữa PHP phiên bản 7 và 8 là gì?

Bản cập nhật lớn mới này mang lại nhiều tối ưu hóa và các tính năng mạnh mẽ cho ngôn ngữ. Chúng tôi rất vui khi được hướng dẫn bạn những thay đổi thú vị nhất sẽ cho phép chúng tôi viết mã tốt hơn và xây dựng các ứng dụng mạnh mẽ hơn

PHP8. 0 Phụ lục thông báo

Bạn đã sẵn sàng chưa?

PHP JIT [Trình biên dịch đúng lúc]

Tính năng được hoan nghênh nhất đi kèm với PHP 8 là trình biên dịch Just-in-time [JIT]. JIT là gì?

Đề xuất RFC mô tả JIT như sau

“PHP JIT được triển khai như một phần gần như độc lập của OPcache. Nó có thể được bật/tắt tại thời điểm biên dịch PHP và tại thời điểm chạy. Khi được bật, mã gốc của các tệp PHP được lưu trữ trong một vùng bổ sung của bộ nhớ dùng chung OPcache và op_array→opcodes[]. [các] trình xử lý giữ con trỏ tới các điểm nhập của mã JIT-ed. ”

Vì vậy, làm thế nào chúng ta có được JIT, và sự khác biệt giữa JIT so với OPcache là gì?

Kinsta chiều chuộng tôi đến mức bây giờ tôi yêu cầu mức độ dịch vụ đó từ mọi nhà cung cấp. Chúng tôi cũng cố gắng đạt được mức đó với sự hỗ trợ của công cụ SaaS

Suganthan Mohanadasan từ @Suganthanmn
Xem kế hoạch

Để hiểu rõ hơn JIT là gì đối với PHP, chúng ta hãy xem nhanh cách PHP thực thi mã nguồn cho đến kết quả cuối cùng

Việc thực thi PHP là một quá trình gồm 4 giai đoạn

  • Lexing/Tokenizing. Đầu tiên, trình thông dịch đọc mã PHP và xây dựng một bộ mã thông báo
  • phân tích cú pháp. Trình thông dịch kiểm tra xem tập lệnh có khớp với quy tắc cú pháp hay không và sử dụng mã thông báo để xây dựng Cây cú pháp trừu tượng [AST], một biểu diễn phân cấp cấu trúc của mã nguồn
  • biên soạn. Trình thông dịch duyệt qua cây và dịch các nút AST thành mã lệnh Zend cấp thấp, là mã định danh số xác định loại lệnh được thực hiện bởi Zend VM
  • Diễn dịch. Opcodes được giải thích và chạy trên Zend VM

Hình ảnh sau đây cho thấy một đại diện trực quan của quá trình thực thi PHP cơ bản

Quy trình thực thi PHP cơ bản

Vậy OPcache làm cho PHP nhanh hơn như thế nào?

Tiện ích mở rộng OPcache

PHP là ngôn ngữ thông dịch. Điều này có nghĩa là, khi một tập lệnh PHP chạy, trình thông dịch sẽ phân tích cú pháp, biên dịch và thực thi mã lặp đi lặp lại trên mỗi yêu cầu. Điều này có thể dẫn đến lãng phí tài nguyên CPU và thêm thời gian

Đây là nơi tiện ích mở rộng OPcache phát huy tác dụng

“OPcache cải thiện hiệu suất PHP bằng cách lưu trữ mã byte của tập lệnh được biên dịch sẵn trong bộ nhớ dùng chung, do đó loại bỏ nhu cầu PHP tải và phân tích cú pháp tập lệnh trên mỗi yêu cầu. ”

Khi bật OPcache, trình thông dịch PHP chỉ trải qua quy trình 4 giai đoạn được đề cập ở trên khi tập lệnh chạy lần đầu tiên. Do mã byte PHP được lưu trữ trong bộ nhớ dùng chung, nên chúng có sẵn ngay lập tức dưới dạng biểu diễn trung gian cấp thấp và có thể được thực thi ngay trên máy ảo Zend

Quy trình thực thi PHP có bật OPcache

Kể từ PHP 5. 5, tiện ích mở rộng Zend OPcache có sẵn theo mặc định và bạn có thể kiểm tra xem mình đã định cấu hình đúng chưa bằng cách gọi

class Test {
    // Error: Using null default on non-nullable property
    public function __construct[public Type $prop = null] {}

    // Correct: Make the type explicitly nullable instead
    public function __construct[public ?Type $prop = null] {}
}
7 từ tập lệnh trên máy chủ của bạn hoặc kiểm tra tệp php của bạn. ini [xem cài đặt cấu hình OPcache]

Cách đọc được đề nghị. Cách cải thiện giới hạn bộ nhớ PHP trong WordPress

Phần Zend OPcache trong trang phpinfo

tải trước

OPcache gần đây đã được cải tiến với việc triển khai tính năng tải trước, một tính năng OPcache mới được bổ sung với PHP 7. 4. Tải trước cung cấp một cách để lưu trữ một tập lệnh được chỉ định vào bộ nhớ OPcache “trước khi bất kỳ mã ứng dụng nào được chạy. ” Tuy nhiên, nó không mang lại sự cải thiện rõ rệt về hiệu suất cho các ứng dụng dựa trên web điển hình

Bạn có thể đọc thêm về tải trước trong phần giới thiệu của chúng tôi về PHP 7. 4

Với JIT, PHP tiến thêm một bước

JIT — Trình biên dịch đúng lúc

Ngay cả khi opcode là biểu diễn trung gian cấp thấp, chúng vẫn phải được biên dịch thành mã máy. JIT “không giới thiệu bất kỳ biểu mẫu IR [Biểu diễn trung gian] bổ sung nào”, nhưng sử dụng DynASM [Trình biên dịch động cho các công cụ tạo mã] để tạo mã gốc trực tiếp từ mã byte PHP

Nói tóm lại, JIT dịch các phần nóng của mã trung gian thành mã máy. Bỏ qua quá trình biên dịch, nó có thể mang lại những cải tiến đáng kể về hiệu suất và mức sử dụng bộ nhớ

Zeev Surasky, đồng tác giả của đề xuất PHP JIT, cho thấy mức độ tính toán sẽ nhanh hơn với JIT

Nhưng liệu JIT có cải thiện hiệu suất WordPress một cách hiệu quả không?

JIT cho các ứng dụng web trực tiếp

Theo JIT RFC, việc triển khai trình biên dịch kịp thời sẽ cải thiện hiệu suất PHP. Nhưng liệu chúng ta có thực sự trải nghiệm những cải tiến như vậy trong các ứng dụng thực tế như WordPress không?

Các thử nghiệm ban đầu cho thấy JIT sẽ giúp khối lượng công việc sử dụng nhiều CPU chạy nhanh hơn đáng kể. Tuy nhiên, RFC cảnh báo

“… giống như những lần thử trước – hiện tại nó dường như không cải thiện đáng kể các ứng dụng thực tế như WordPress [với opcache. jit=1235 326 yêu cầu/giây so với 315 yêu cầu/giây]

Nó được lên kế hoạch cung cấp thêm nỗ lực, cải thiện JIT cho các ứng dụng thực tế, sử dụng tối ưu hóa hồ sơ và đầu cơ. ”

Khi bật JIT, mã sẽ không được chạy bởi Zend VM mà bởi chính CPU, điều này sẽ cải thiện tốc độ tính toán. Các ứng dụng web như WordPress cũng dựa vào các yếu tố khác như TTFB, tối ưu hóa cơ sở dữ liệu, yêu cầu HTTP, v.v.

Đóng góp JIT tương đối vào hiệu suất PHP 8 [Nguồn hình ảnh. PHP8. 0 Phụ lục Thông báo]

Vì vậy, chúng ta không nên mong đợi một sự gia tăng đáng kể về tốc độ thực thi PHP khi nói đến WordPress và các ứng dụng tương tự. Tuy nhiên, JIT có thể mang lại một số lợi ích cho các nhà phát triển

Theo Nikita Popov

“Lợi ích của trình biên dịch JIT là đại khái [và như đã được nêu trong RFC]

  • Hiệu suất tốt hơn đáng kể cho mã số
  • Hiệu suất tốt hơn một chút đối với mã ứng dụng web PHP “điển hình”
  • Khả năng chuyển nhiều mã hơn từ C sang PHP, bởi vì PHP bây giờ sẽ đủ nhanh. ”

Vì vậy, mặc dù JIT sẽ khó mang lại những cải tiến lớn cho hiệu suất của WordPress, nhưng nó sẽ nâng cấp PHP lên cấp độ tiếp theo, biến nó thành ngôn ngữ mà nhiều chức năng hiện có thể được viết trực tiếp bằng

Nhược điểm sẽ là độ phức tạp lớn hơn có thể làm tăng chi phí bảo trì, ổn định và gỡ lỗi. Theo Dmitri Stogov

“JIT cực kỳ đơn giản, nhưng dù sao thì nó cũng làm tăng mức độ phức tạp của toàn bộ PHP, nguy cơ xuất hiện các loại lỗi mới và chi phí phát triển và bảo trì. ”

Đề xuất đưa JIT vào PHP 8 được thông qua với 50 phiếu chống 2 phiếu

PHP 8 đã có tại đây. 🚀 Hãy xem phần tìm hiểu sâu của chúng tôi về các tính năng mới. Nhấp để Tweet

Các cải tiến và tính năng mới của PHP 8

Ngoài JIT, chúng ta có thể mong đợi nhiều tính năng và cải tiến với PHP 8. Danh sách sau đây là lựa chọn cẩn thận của chúng tôi về các bổ sung và thay đổi sắp tới sẽ làm cho PHP trở nên đáng tin cậy và hiệu quả hơn

Khuyến mãi bất động sản xây dựng

Là kết quả của một cuộc thảo luận đang diễn ra về việc cải thiện công thái học của đối tượng trong PHP, RFC Quảng cáo Thuộc tính Trình xây dựng đề xuất một cú pháp mới và ngắn gọn hơn sẽ đơn giản hóa việc khai báo thuộc tính, làm cho nó ngắn hơn và ít thừa hơn

Đề xuất này chỉ liên quan đến các tham số được thăng cấp, tôi. e. các tham số phương thức đó có tiền tố là các từ khóa hiển thị công khai, được bảo vệ và riêng tư

Hiện tại, tất cả các thuộc tính phải được lặp lại nhiều lần [ít nhất bốn lần] trước khi chúng ta có thể sử dụng chúng với các đối tượng. Xem xét ví dụ sau từ RFC

class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}

Theo Nikita Popov, tác giả RFC, chúng ta phải viết tên thuộc tính ít nhất bốn lần ở ba vị trí khác nhau. khai báo thuộc tính, tham số hàm tạo và gán thuộc tính. Cú pháp này đặc biệt không sử dụng được, đặc biệt là trong các lớp có nhiều thuộc tính và nhiều tên mô tả hơn

RFC này đề xuất hợp nhất hàm tạo và định nghĩa tham số. Vì vậy, kể từ PHP 8, chúng ta có một cách khai báo tham số dễ sử dụng hơn. Mã nhìn thấy ở trên có thể thay đổi như hình dưới đây

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}

Và đó là nó. Vì vậy, chúng tôi có một cách mới để quảng cáo các thuộc tính ngắn hơn, dễ đọc hơn và ít bị lỗi hơn. Theo Nikita

Đó là một phép biến đổi cú pháp đơn giản mà chúng tôi đang thực hiện. Nhưng điều đó làm giảm số lượng mã soạn sẵn mà bạn phải viết cho các đối tượng giá trị nói riêng…

Khai báo thuộc tính được chuyển đổi khi chúng ta khai báo rõ ràng các thuộc tính đó và chúng ta có thể sử dụng API Reflection để xem xét các định nghĩa thuộc tính trước khi thực thi [xem Giải thích]

Phản xạ [và các cơ chế nội quan khác] sẽ quan sát trạng thái sau khi khử đường. Điều này có nghĩa là các thuộc tính được thăng cấp sẽ xuất hiện giống như các thuộc tính được khai báo rõ ràng và các đối số hàm tạo được thăng cấp sẽ xuất hiện dưới dạng các đối số hàm tạo thông thường

// before desugaring
class Point {
    public function __construct[public int $x = 0] {}
}

// after desugaring
class Point {
    public int $x;

    public function __construct[int $x = 0] {
        $this->x = $x;
    }
}

Di sản

Chúng tôi không có bất kỳ giới hạn nào trong việc sử dụng tính kế thừa kết hợp với các tham số được thăng cấp. Dù sao, không có mối quan hệ cụ thể nào giữa các hàm tạo của lớp cha và lớp con. Theo Nikita

Thông thường, chúng ta nói rằng các phương thức luôn phải tương thích với phương thức cha. […] nhưng quy tắc này không áp dụng cho hàm tạo. Vì vậy, hàm tạo thực sự thuộc về một lớp duy nhất và các hàm tạo giữa lớp cha và lớp con không nhất thiết phải tương thích theo bất kỳ cách nào

Đây là một ví dụ

class Test {
    public function __construct[
        public int $x = 0
    ] {}
}

class Child extends Test {
    public function __construct[
        $x, 
        public int $y = 0,
        public int $z = 0,
    ] {
        parent::__construct[$x];
    }
}

Điều gì không được phép với các thuộc tính được quảng cáo

Các thuộc tính được quảng cáo được cho phép trong các hàm tạo và đặc điểm không trừu tượng, nhưng có một số hạn chế đáng được đề cập ở đây

Trình xây dựng trừu tượng

Các thuộc tính được quảng cáo không được phép trong các lớp và giao diện trừu tượng

abstract class Test {
    // Error: Abstract constructor.
    abstract public function __construct[private $x];
}
 
interface Test {
    // Error: Abstract constructor.
    public function __construct[private $x];
}
Nullability

Một trong những ràng buộc đáng chú ý nhất có liên quan đến tính vô hiệu. Trước đây, chúng tôi đã sử dụng một loại không thể vô hiệu hóa một cách rõ ràng. Nhưng với giá trị mặc định null, loại này hoàn toàn có thể vô hiệu hóa. Nhưng với các loại thuộc tính, chúng tôi không có hành vi ngầm định này vì các tham số được thăng cấp yêu cầu khai báo thuộc tính và loại nullable phải được khai báo rõ ràng. Xem ví dụ sau từ RFC

class Test {
    // Error: Using null default on non-nullable property
    public function __construct[public Type $prop = null] {}

    // Correct: Make the type explicitly nullable instead
    public function __construct[public ?Type $prop = null] {}
}
Loại có thể gọi

Vì thuộc tính có thể gọi được không phải là loại được hỗ trợ nên chúng tôi không được phép sử dụng loại có thể gọi được trong thuộc tính được quảng cáo

class Test {
    // Error: Callable type not supported for properties.
    public function __construct[public callable $callback] {}
}
Từ khóa var không được phép

Chỉ có thể sử dụng từ khóa khả năng hiển thị với các tham số được thăng cấp, vì vậy không được phép khai báo các thuộc tính hàm tạo bằng từ khóa

class Test {
    // Error: Using null default on non-nullable property
    public function __construct[public Type $prop = null] {}

    // Correct: Make the type explicitly nullable instead
    public function __construct[public ?Type $prop = null] {}
}
8 [xem ví dụ sau từ RFC]

class Test {
    // Error: "var" keyword is not supported.
    public function __construct[var $prop] {}
}
Không cho phép trùng lặp

Chúng ta có thể kết hợp các thuộc tính được thăng cấp và các thuộc tính rõ ràng trong cùng một lớp, nhưng các thuộc tính không thể được khai báo hai lần

class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
0Tham số biến thể không được phép

Lý do ở đây là kiểu được khai báo khác với tham số matrixdic, mà thực chất là một mảng

class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
1

Đọc thêm

Để có cái nhìn cận cảnh hơn về Quảng cáo tài sản xây dựng, hãy nghe cuộc phỏng vấn này với Nikita Popov. Để có cái nhìn tổng quan chuyên sâu về công thái học của đối tượng trong PHP, hãy xem bài đăng này và cuộc phỏng vấn sau đây với Larry Garfield

Xác thực cho các phương thức đặc điểm trừu tượng

Các đặc điểm được định nghĩa là “một cơ chế tái sử dụng mã trong các ngôn ngữ kế thừa đơn lẻ như PHP. ” Thông thường, chúng được sử dụng để khai báo các phương thức có thể được sử dụng trong nhiều lớp

Một đặc điểm cũng có thể chứa các phương thức trừu tượng. Các phương thức này chỉ đơn giản khai báo chữ ký của phương thức, nhưng việc triển khai phương thức phải được thực hiện trong lớp bằng cách sử dụng đặc điểm

Theo hướng dẫn sử dụng PHP,

“Các đặc điểm hỗ trợ việc sử dụng các phương pháp trừu tượng để áp đặt các yêu cầu đối với lớp thể hiện. ”

Điều này cũng có nghĩa là chữ ký của các phương thức phải khớp. Nói cách khác, loại và số lượng đối số bắt buộc phải giống nhau

Dù sao đi nữa, theo Nikita Popov, tác giả của RFC, việc xác thực chữ ký hiện chỉ được thi hành đột ngột

  • Nó không được thực thi trong trường hợp phổ biến nhất, trong đó việc triển khai phương thức được cung cấp bởi lớp sử dụng. https. //3v4l. tổ chức/SeVK3
  • Nó được thi hành nếu việc triển khai đến từ một lớp cha. https. //3v4l. org/4VCip
  • Nó được thực thi nếu việc triển khai đến từ một lớp con. https. //3v4l. tổ chức/q7Bq2

Ví dụ sau đây từ Nikita liên quan đến trường hợp đầu tiên [chữ ký không bắt buộc]

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
0

Như đã nói, RFC này đề xuất luôn đưa ra một lỗi nghiêm trọng nếu phương thức triển khai không tương thích với phương thức đặc điểm trừu tượng, bất kể nguồn gốc của nó

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
1

RFC này đã được nhất trí thông qua

Chữ ký phương thức không tương thích

Trong PHP, lỗi kế thừa do chữ ký phương thức không tương thích sẽ gây ra lỗi nghiêm trọng hoặc cảnh báo tùy thuộc vào nguyên nhân gây ra lỗi

Nếu một lớp đang triển khai một giao diện, các chữ ký phương thức không tương thích sẽ gây ra lỗi nghiêm trọng. Theo tài liệu Giao diện đối tượng

“Lớp triển khai giao diện phải sử dụng chữ ký phương thức tương thích với LSP [Nguyên tắc thay thế Liskov]. Không làm như vậy sẽ dẫn đến một lỗi nghiêm trọng. ”

Dưới đây là một ví dụ về lỗi thừa kế với giao diện

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
2

Trong PHP7. 4, đoạn mã trên sẽ đưa ra lỗi sau

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
3

Một hàm trong lớp con có chữ ký không tương thích sẽ đưa ra cảnh báo. Xem đoạn mã sau từ RFC

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
4

Trong PHP7. 4, đoạn mã trên sẽ chỉ đưa ra một cảnh báo

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
5

Bây giờ, RFC này đề xuất luôn đưa ra một lỗi nghiêm trọng đối với các chữ ký phương thức không tương thích. Với PHP 8, mã mà chúng ta đã thấy trước đó ở trên sẽ nhắc như sau

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
6

Mảng bắt đầu với một chỉ số tiêu cực

Trong PHP, nếu một mảng bắt đầu bằng một chỉ số âm [_______09], thì các chỉ mục sau sẽ bắt đầu từ 0 [thêm về điều này trong tài liệu

class Test {
    // Error: Callable type not supported for properties.
    public function __construct[public callable $callback] {}
}
0]. Nhìn vào ví dụ sau

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
7

Trong PHP7. 4 kết quả sẽ như sau

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
8

Bây giờ, RFC này đề xuất thay đổi mọi thứ sao cho chỉ số thứ hai sẽ là

class Test {
    // Error: Callable type not supported for properties.
    public function __construct[public callable $callback] {}
}
1, bất kể giá trị của
class Test {
    // Error: Callable type not supported for properties.
    public function __construct[public callable $callback] {}
}
2 là bao nhiêu

Trong PHP 8, đoạn mã trên sẽ dẫn đến mảng sau

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
9

Với PHP 8, các mảng bắt đầu bằng chỉ mục âm sẽ thay đổi hành vi của chúng. Đọc thêm về sự không tương thích ngược trong RFC

Liên minh loại 2. 0

Các loại liên kết chấp nhận các giá trị có thể thuộc các loại khác nhau. Hiện tại, PHP không cung cấp hỗ trợ cho các kiểu kết hợp, ngoại trừ cú pháp

class Test {
    // Error: Callable type not supported for properties.
    public function __construct[public callable $callback] {}
}
3 và kiểu đặc biệt
class Test {
    // Error: Callable type not supported for properties.
    public function __construct[public callable $callback] {}
}
4

Trước PHP 8, các loại liên kết chỉ có thể được chỉ định trong các chú thích phpdoc, như được hiển thị trong ví dụ sau từ RFC

// before desugaring
class Point {
    public function __construct[public int $x = 0] {}
}

// after desugaring
class Point {
    public int $x;

    public function __construct[int $x = 0] {
        $this->x = $x;
    }
}
0

Bây giờ, Liên minh loại 2. 0 RFC đề xuất thêm hỗ trợ cho các loại liên kết trong chữ ký hàm, vì vậy chúng tôi sẽ không dựa vào tài liệu nội tuyến nữa mà thay vào đó sẽ xác định các loại liên kết bằng cú pháp

class Test {
    // Error: Callable type not supported for properties.
    public function __construct[public callable $callback] {}
}
5

// before desugaring
class Point {
    public function __construct[public int $x = 0] {}
}

// after desugaring
class Point {
    public int $x;

    public function __construct[int $x = 0] {
        $this->x = $x;
    }
}
1

Theo giải thích của Nikita Popov trong RFC,

“Việc hỗ trợ các kiểu kết hợp trong ngôn ngữ cho phép chúng tôi chuyển nhiều thông tin kiểu hơn từ phpdoc sang các chữ ký hàm, với những lợi thế thông thường mà điều này mang lại

  • Các loại thực sự được thi hành, vì vậy có thể phát hiện sớm các lỗi
  • Bởi vì chúng được thực thi, loại thông tin ít có khả năng trở nên lỗi thời hoặc bỏ lỡ các trường hợp cạnh
  • Các loại được kiểm tra trong quá trình kế thừa, thực thi Nguyên tắc thay thế Liskov
  • Các loại có sẵn thông qua Reflection
  • Cú pháp ít soạn sẵn hơn nhiều so với phpdoc. ”

Các loại liên kết hỗ trợ tất cả các loại có sẵn, với một số hạn chế

  • Loại
    class Test {
        // Error: Callable type not supported for properties.
        public function __construct[public callable $callback] {}
    }
    6 không thể là một phần của liên kết, vì
    class Test {
        // Error: Callable type not supported for properties.
        public function __construct[public callable $callback] {}
    }
    6 có nghĩa là một hàm không trả về bất kỳ giá trị nào
  • Loại
    class Test {
        // Error: Callable type not supported for properties.
        public function __construct[public callable $callback] {}
    }
    8 chỉ được hỗ trợ trong các loại liên kết nhưng không được phép sử dụng loại này như một loại độc lập
  • Ký hiệu loại nullable [
    class Test {
        // Error: Callable type not supported for properties.
        public function __construct[public callable $callback] {}
    }
    9] cũng được cho phép, nghĩa là
    class Test {
        // Error: "var" keyword is not supported.
        public function __construct[var $prop] {}
    }
    0, nhưng chúng tôi không được phép đưa ký hiệu
    class Test {
        // Error: Callable type not supported for properties.
        public function __construct[public callable $callback] {}
    }
    9 vào các loại liên kết [
    class Test {
        // Error: "var" keyword is not supported.
        public function __construct[var $prop] {}
    }
    2 không được phép và thay vào đó chúng tôi nên sử dụng
    class Test {
        // Error: "var" keyword is not supported.
        public function __construct[var $prop] {}
    }
    3]
  • Nhiều chức năng [tôi. e.
    class Test {
        // Error: "var" keyword is not supported.
        public function __construct[var $prop] {}
    }
    4,
    class Test {
        // Error: "var" keyword is not supported.
        public function __construct[var $prop] {}
    }
    5,
    class Test {
        // Error: "var" keyword is not supported.
        public function __construct[var $prop] {}
    }
    6, v.v. ] bao gồm
    class Test {
        // Error: "var" keyword is not supported.
        public function __construct[var $prop] {}
    }
    7 trong số các loại trả về có thể, loại giả
    class Test {
        // Error: "var" keyword is not supported.
        public function __construct[var $prop] {}
    }
    7 cũng được hỗ trợ

Bạn có thể đọc thêm về Union Type V2 trong RFC

Lỗi loại nhất quán cho các chức năng nội bộ

Khi truyền một tham số thuộc loại không hợp lệ, các hàm bên trong và do người dùng định nghĩa sẽ hoạt động khác đi

Các hàm do người dùng định nghĩa tạo ra một

class Test {
    // Error: "var" keyword is not supported.
    public function __construct[var $prop] {}
}
9, nhưng các hàm bên trong hoạt động theo nhiều cách khác nhau, tùy thuộc vào một số điều kiện. Dù sao đi nữa, hành vi điển hình là đưa ra cảnh báo và trả lại
class Test {
    // Error: Callable type not supported for properties.
    public function __construct[public callable $callback] {}
}
8. Xem ví dụ sau trong PHP 7. 4

// before desugaring
class Point {
    public function __construct[public int $x = 0] {}
}

// after desugaring
class Point {
    public int $x;

    public function __construct[int $x = 0] {
        $this->x = $x;
    }
}
2

Điều này sẽ dẫn đến cảnh báo sau

// before desugaring
class Point {
    public function __construct[public int $x = 0] {}
}

// after desugaring
class Point {
    public int $x;

    public function __construct[int $x = 0] {
        $this->x = $x;
    }
}
3

Nếu

class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
01 được bật hoặc thông tin đối số chỉ định loại, hành vi sẽ khác. Trong các trường hợp như vậy, lỗi loại được phát hiện và dẫn đến lỗi
class Test {
    // Error: "var" keyword is not supported.
    public function __construct[var $prop] {}
}
9

Tình huống này sẽ dẫn đến một số vấn đề được giải thích rõ ràng trong phần các vấn đề của RFC

Để loại bỏ những điểm không nhất quán này, RFC này đề xuất tạo các API phân tích tham số nội bộ để luôn tạo một

class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
03 trong trường hợp loại tham số không khớp

Trong PHP 8, đoạn mã trên đưa ra lỗi sau

// before desugaring
class Point {
    public function __construct[public int $x = 0] {}
}

// after desugaring
class Point {
    public int $x;

    public function __construct[int $x = 0] {
        $this->x = $x;
    }
}
4

ném biểu thức

Trong PHP,

class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
04 là một câu lệnh, vì vậy không thể sử dụng nó ở những nơi chỉ cho phép một biểu thức

Đăng kí để nhận thư mới

Bạn muốn biết làm thế nào chúng tôi tăng lưu lượng truy cập của mình hơn 1000%?

Tham gia cùng hơn 20.000 người khác nhận bản tin hàng tuần của chúng tôi với các mẹo nội bộ về WordPress

Theo dõi ngay

RFC này đề xuất chuyển đổi câu lệnh

class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
04 thành một biểu thức để nó có thể được sử dụng trong bất kỳ ngữ cảnh nào cho phép biểu thức. Ví dụ: các hàm mũi tên, toán tử kết hợp null, toán tử ternary và elvis, v.v.

Xem các ví dụ sau từ RFC

// before desugaring
class Point {
    public function __construct[public int $x = 0] {}
}

// after desugaring
class Point {
    public int $x;

    public function __construct[int $x = 0] {
        $this->x = $x;
    }
}
5

Bản đồ yếu

Bản đồ yếu là một tập hợp dữ liệu [đối tượng] trong đó các khóa được tham chiếu yếu, nghĩa là chúng không bị ngăn thu gom rác

PHP7. 4 đã thêm hỗ trợ cho các tham chiếu yếu như một cách để giữ lại tham chiếu đến một đối tượng mà không ngăn chính đối tượng đó bị hủy. Như Nikita Popov đã chỉ ra,

“Bản thân các tham chiếu yếu thô chỉ có tính hữu ích hạn chế và các bản đồ yếu được sử dụng phổ biến hơn nhiều trong thực tế. Không thể triển khai một bản đồ yếu hiệu quả trên các tham chiếu yếu PHP vì khả năng đăng ký gọi lại hủy không được cung cấp. ”

Đó là lý do tại sao RFC này giới thiệu lớp

class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
06 để tạo các đối tượng được sử dụng làm khóa bản đồ yếu có thể bị hủy và xóa khỏi bản đồ yếu nếu không có bất kỳ tham chiếu nào khác đến đối tượng chính

Trong các quy trình chạy dài, điều này sẽ ngăn rò rỉ bộ nhớ và cải thiện hiệu suất. Xem ví dụ sau từ RFC

// before desugaring
class Point {
    public function __construct[public int $x = 0] {}
}

// after desugaring
class Point {
    public int $x;

    public function __construct[int $x = 0] {
        $this->x = $x;
    }
}
6

Với PHP 8, đoạn mã trên sẽ tạo ra kết quả như sau [xem mã đang hoạt động tại đây]

// before desugaring
class Point {
    public function __construct[public int $x = 0] {}
}

// after desugaring
class Point {
    public int $x;

    public function __construct[int $x = 0] {
        $this->x = $x;
    }
}
7

Nếu bạn bỏ đặt đối tượng, khóa sẽ tự động bị xóa khỏi bản đồ yếu

// before desugaring
class Point {
    public function __construct[public int $x = 0] {}
}

// after desugaring
class Point {
    public int $x;

    public function __construct[int $x = 0] {
        $this->x = $x;
    }
}
8

Bây giờ kết quả sẽ như sau

// before desugaring
class Point {
    public function __construct[public int $x = 0] {}
}

// after desugaring
class Point {
    public int $x;

    public function __construct[int $x = 0] {
        $this->x = $x;
    }
}
9

Để xem kỹ hơn về Bản đồ yếu, hãy xem RFC. Đề xuất đã được nhất trí thông qua

Dấu phẩy trong danh sách tham số

Dấu phẩy ở cuối là dấu phẩy được thêm vào danh sách các mục trong các ngữ cảnh khác nhau. PHP7. 2 giới thiệu dấu phẩy ở cuối trong cú pháp danh sách, PHP 7. 3 dấu phẩy được giới thiệu trong các lời gọi hàm

PHP 8 hiện giới thiệu dấu phẩy ở cuối danh sách tham số với các hàm, phương thức và bao đóng, như trong ví dụ sau

class Test {
    public function __construct[
        public int $x = 0
    ] {}
}

class Child extends Test {
    public function __construct[
        $x, 
        public int $y = 0,
        public int $z = 0,
    ] {
        parent::__construct[$x];
    }
}
0

Đề xuất này được thông qua với số phiếu 58 ăn 1

Cho phép. cú pháp lớp trên các đối tượng

Để lấy tên của một lớp, chúng ta có thể sử dụng cú pháp

class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
07. RFC này đề xuất mở rộng cú pháp tương tự cho các đối tượng để giờ đây có thể tìm nạp tên của lớp của một đối tượng nhất định, như trong ví dụ bên dưới

class Test {
    public function __construct[
        public int $x = 0
    ] {}
}

class Child extends Test {
    public function __construct[
        $x, 
        public int $y = 0,
        public int $z = 0,
    ] {
        parent::__construct[$x];
    }
}
1

Với PHP 8,

class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
08 cung cấp kết quả tương tự như
class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
09. Nếu
class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
10 không phải là một đối tượng, nó sẽ đưa ra một ngoại lệ
class Test {
    // Error: "var" keyword is not supported.
    public function __construct[var $prop] {}
}
9

Đề xuất này đã được nhất trí thông qua

Thuộc tính v2

Thuộc tính, còn được gọi là chú thích, là siêu dữ liệu có cấu trúc có thể được sử dụng để chỉ định thuộc tính cho đối tượng, thành phần hoặc tệp

Cho đến PHP 7. 4, doc-comment là cách duy nhất để thêm siêu dữ liệu vào phần khai báo của các lớp, hàm, v.v. Các thuộc tính v2 RFC giới thiệu các thuộc tính PHP, định nghĩa chúng như một dạng siêu dữ liệu có cấu trúc, cú pháp có thể được thêm vào các khai báo của các lớp, thuộc tính, hàm, phương thức, tham số và hằng số

Các thuộc tính được thêm vào trước các khai báo mà chúng đề cập đến. Xem các ví dụ sau từ RFC

class Test {
    public function __construct[
        public int $x = 0
    ] {}
}

class Child extends Test {
    public function __construct[
        $x, 
        public int $y = 0,
        public int $z = 0,
    ] {
        parent::__construct[$x];
    }
}
2

Các thuộc tính có thể được thêm vào trước hoặc sau nhận xét khối tài liệu

class Test {
    public function __construct[
        public int $x = 0
    ] {}
}

class Child extends Test {
    public function __construct[
        $x, 
        public int $y = 0,
        public int $z = 0,
    ] {
        parent::__construct[$x];
    }
}
3

Mỗi khai báo có thể có một hoặc nhiều thuộc tính và mỗi thuộc tính có thể có một hoặc nhiều giá trị liên quan

class Test {
    public function __construct[
        public int $x = 0
    ] {}
}

class Child extends Test {
    public function __construct[
        $x, 
        public int $y = 0,
        public int $z = 0,
    ] {
        parent::__construct[$x];
    }
}
4

Xem RFC để biết tổng quan sâu hơn về các thuộc tính PHP, trường hợp sử dụng và cú pháp thay thế

Đối số được đặt tên

Các đối số được đặt tên cung cấp một cách mới để truyền đối số cho một hàm trong PHP

Đối số được đặt tên cho phép truyền đối số cho hàm dựa trên tên tham số, thay vì vị trí tham số

Chúng ta có thể truyền các đối số được đặt tên cho một hàm bằng cách thêm tên tham số trước giá trị của nó

class Test {
    public function __construct[
        public int $x = 0
    ] {}
}

class Child extends Test {
    public function __construct[
        $x, 
        public int $y = 0,
        public int $z = 0,
    ] {
        parent::__construct[$x];
    }
}
5

Chúng tôi cũng được phép sử dụng các từ khóa dành riêng, như trong ví dụ bên dưới

class Test {
    public function __construct[
        public int $x = 0
    ] {}
}

class Child extends Test {
    public function __construct[
        $x, 
        public int $y = 0,
        public int $z = 0,
    ] {
        parent::__construct[$x];
    }
}
6

Nhưng chúng tôi không được phép chuyển tên tham số động. Tham số phải là một mã định danh và cú pháp sau không được phép

class Test {
    public function __construct[
        public int $x = 0
    ] {}
}

class Child extends Test {
    public function __construct[
        $x, 
        public int $y = 0,
        public int $z = 0,
    ] {
        parent::__construct[$x];
    }
}
7

Theo Nikita Popov, tác giả của RFC này, các đối số được đặt tên mang lại một số lợi thế

Trước hết, các đối số được đặt tên sẽ giúp chúng ta viết mã dễ hiểu hơn vì ý nghĩa của chúng là tự ghi lại. Ví dụ dưới đây từ RFC là tự giải thích

class Test {
    public function __construct[
        public int $x = 0
    ] {}
}

class Child extends Test {
    public function __construct[
        $x, 
        public int $y = 0,
        public int $z = 0,
    ] {
        parent::__construct[$x];
    }
}
8

Các đối số được đặt tên không phụ thuộc vào thứ tự. Điều này có nghĩa là chúng ta không buộc phải truyền đối số cho hàm theo thứ tự như chữ ký hàm

Cần một dịch vụ lưu trữ cực nhanh, an toàn và thân thiện với nhà phát triển cho trang web của bạn? . Kiểm tra kế hoạch của chúng tôi

class Test {
    public function __construct[
        public int $x = 0
    ] {}
}

class Child extends Test {
    public function __construct[
        $x, 
        public int $y = 0,
        public int $z = 0,
    ] {
        parent::__construct[$x];
    }
}
9

Cũng có thể kết hợp các đối số được đặt tên với các đối số vị trí

abstract class Test {
    // Error: Abstract constructor.
    abstract public function __construct[private $x];
}
 
interface Test {
    // Error: Abstract constructor.
    public function __construct[private $x];
}
0

Một ưu điểm lớn khác của các đối số được đặt tên là chúng chỉ cho phép chỉ định những đối số mà chúng ta muốn thay đổi. Chúng tôi không phải chỉ định các đối số mặc định nếu chúng tôi không muốn ghi đè lên các giá trị mặc định. Ví dụ sau từ RFC làm rõ

abstract class Test {
    // Error: Abstract constructor.
    abstract public function __construct[private $x];
}
 
interface Test {
    // Error: Abstract constructor.
    public function __construct[private $x];
}
1

Quan trọng

Nếu bạn là nhà phát triển WordPress, xin lưu ý rằng tại thời điểm viết bài này, các đối số được đặt tên có thể dẫn đến các vấn đề tương thích ngược. Không sử dụng chúng trong sản xuất mà không kiểm tra chu đáo

Các đối số được đặt tên có thể được sử dụng với các thuộc tính PHP, như được hiển thị trong ví dụ sau từ RFC

abstract class Test {
    // Error: Abstract constructor.
    abstract public function __construct[private $x];
}
 
interface Test {
    // Error: Abstract constructor.
    public function __construct[private $x];
}
2

Tuy nhiên, việc chuyển các đối số vị trí sau các đối số được đặt tên là không được phép và sẽ dẫn đến lỗi thời gian biên dịch. Điều tương tự cũng xảy ra khi bạn chuyển cùng một tên tham số hai lần

Các đối số được đặt tên rất tiện lợi với các khai báo lớp vì các hàm tạo thường có nhiều tham số và các đối số được đặt tên cung cấp một cách “công thái học” hơn để khai báo một lớp

Để xem kỹ hơn về Đối số được đặt tên, với các ràng buộc, tính không tương thích ngược và một số ví dụ, hãy xem Đối số được đặt tên RFC

Toán tử Nullsafe

RFC này giới thiệu toán tử nullsafe

class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
12 với đánh giá ngắn mạch đầy đủ

Trong đánh giá ngắn mạch, toán tử thứ hai chỉ được đánh giá nếu toán tử thứ nhất không đánh giá thành

class Test {
    // Error: Callable type not supported for properties.
    public function __construct[public callable $callback] {}
}
8. Nếu một toán tử trong chuỗi đánh giá là
class Test {
    // Error: Callable type not supported for properties.
    public function __construct[public callable $callback] {}
}
8, thì việc thực thi toàn bộ chuỗi sẽ dừng lại và đánh giá là
class Test {
    // Error: Callable type not supported for properties.
    public function __construct[public callable $callback] {}
}
8

Xem xét các ví dụ sau từ RFC

abstract class Test {
    // Error: Abstract constructor.
    abstract public function __construct[private $x];
}
 
interface Test {
    // Error: Abstract constructor.
    public function __construct[private $x];
}
3

Nếu

class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
16 là null, phương thức
class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
17 không được gọi và
class Point {
    public int $x;
    public int $y;
    public int $z;

    public function __construct[
        int $x = 0,
        int $y = 0,
        int $z = 0,
    ] {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}
18 được đặt thành
class Test {
    // Error: Callable type not supported for properties.
    public function __construct[public callable $callback] {}
}
8

Xem RFC toán tử nullsafe để biết thêm các ví dụ, ngoại lệ và phạm vi trong tương lai

So sánh chuỗi Saner với số

Trong các phiên bản PHP trước, khi thực hiện so sánh không nghiêm ngặt giữa các chuỗi và số, trước tiên PHP sẽ chuyển chuỗi thành một số, sau đó thực hiện so sánh giữa các số nguyên hoặc số float. Ngay cả khi hành vi này khá hữu ích trong một số trường hợp, nó có thể tạo ra kết quả sai và cũng có thể dẫn đến lỗi và/hoặc sự cố bảo mật

Xem xét ví dụ sau từ RFC

abstract class Test {
    // Error: Abstract constructor.
    abstract public function __construct[private $x];
}
 
interface Test {
    // Error: Abstract constructor.
    public function __construct[private $x];
}
4

PHP 8 giới thiệu chuỗi Saner để so sánh số, nhằm mục đích làm cho chuỗi so sánh với số hợp lý hơn. Theo lời của Nikita Popov,

RFC này dự định cung cấp cho chuỗi để so sánh số một hành vi hợp lý hơn. Khi so sánh với một chuỗi số, hãy sử dụng phép so sánh số [giống như bây giờ]. Nếu không, hãy chuyển đổi số thành chuỗi và sử dụng phép so sánh chuỗi

Bảng sau đây so sánh hành vi của so sánh chuỗi với số trong các phiên bản PHP trước đó và trong PHP 8

abstract class Test {
    // Error: Abstract constructor.
    abstract public function __construct[private $x];
}
 
interface Test {
    // Error: Abstract constructor.
    public function __construct[private $x];
}
5

Đọc thêm về nhiều ý nghĩa của thay đổi này và cách so sánh chuỗi với số thay đổi trong PHP 8 trong RFC chính thức từ Nikita Popov

Chuỗi số Saner

Trong PHP, các chuỗi chứa số được chia thành ba loại

  • chuỗi số. các chuỗi chứa một số tùy ý đứng trước khoảng trắng
  • Chuỗi số hàng đầu. chuỗi có ký tự đầu là chuỗi số và ký tự cuối không phải là số
  • chuỗi không phải số. chuỗi không thuộc cả hai loại trước đó

Chuỗi số và chuỗi số đầu được xử lý khác nhau tùy thuộc vào thao tác được thực hiện. Ví dụ

  • Chuyển đổi chuỗi thành số rõ ràng [i. e. Phôi loại
    class Point {
        public function __construct[
            public int $x = 0,
            public int $y = 0,
            public int $z = 0,
        ] {}
    }
    00 và
    class Point {
        public function __construct[
            public int $x = 0,
            public int $y = 0,
            public int $z = 0,
        ] {}
    }
    01] chuyển đổi các số chuỗi số và số ở đầu. Chuyển đổi rõ ràng một chuỗi không phải số thành một số tạo ra 0
  • Chuyển đổi chuỗi ẩn thành số [i. e. không có khai báo
    class Point {
        public function __construct[
            public int $x = 0,
            public int $y = 0,
            public int $z = 0,
        ] {}
    }
    02] dẫn đến các kết quả khác nhau đối với các chuỗi số và không phải số. Chuyển đổi chuỗi không phải số thành số ném một
    class Test {
        // Error: "var" keyword is not supported.
        public function __construct[var $prop] {}
    }
    9
  • class Point {
        public function __construct[
            public int $x = 0,
            public int $y = 0,
            public int $z = 0,
        ] {}
    }
    04 chỉ trả về true cho các chuỗi số

Độ lệch chuỗi, phép toán số học, phép toán tăng và giảm, so sánh chuỗi với chuỗi và phép toán bitwise cũng dẫn đến các kết quả khác nhau

RFC này đề xuất

Hợp nhất các chế độ chuỗi số khác nhau thành một khái niệm duy nhất. Các ký tự số chỉ được phép có cả khoảng trắng ở đầu và cuối. Bất kỳ loại chuỗi nào khác không phải là số và sẽ ném TypeErrors khi được sử dụng trong ngữ cảnh số

Điều này có nghĩa là, tất cả các chuỗi hiện đang phát ra E_NOTICE “Đã gặp phải giá trị số không được định dạng tốt” sẽ được phân loại lại thành E_WARNING “Đã gặp phải giá trị không phải là số” trừ khi chuỗi có số ở đầu chỉ chứa khoảng trắng ở cuối. Và các trường hợp khác nhau hiện đang phát ra E_WARNING sẽ được thăng cấp lên

class Test {
    // Error: "var" keyword is not supported.
    public function __construct[var $prop] {}
}
9

Để biết tổng quan sâu hơn về các chuỗi số trong PHP 8, với các ví dụ mã, ngoại lệ và các vấn đề tương thích ngược, hãy xem RFC

Biểu thức đối sánh v2

Biểu thức

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
06 mới khá giống với
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
07 nhưng có ngữ nghĩa an toàn hơn và cho phép trả về các giá trị

Để hiểu sự khác biệt giữa hai cấu trúc điều khiển, hãy xem xét ví dụ

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
07 sau từ RFC

abstract class Test {
    // Error: Abstract constructor.
    abstract public function __construct[private $x];
}
 
interface Test {
    // Error: Abstract constructor.
    public function __construct[private $x];
}
6

Bây giờ chúng ta có thể nhận được kết quả tương tự như đoạn mã trên với biểu thức

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
06 sau

abstract class Test {
    // Error: Abstract constructor.
    abstract public function __construct[private $x];
}
 
interface Test {
    // Error: Abstract constructor.
    public function __construct[private $x];
}
7

Một lợi thế đáng kể của việc sử dụng biểu thức

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
06 mới là trong khi
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
07 so sánh lỏng lẻo các giá trị [
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
12] có khả năng dẫn đến kết quả không mong muốn, thì với
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
06, so sánh là kiểm tra danh tính [
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
14]

Biểu thức

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
06 cũng có thể chứa nhiều biểu thức được phân tách bằng dấu phẩy cho phép cú pháp ngắn gọn hơn [nguồn]

abstract class Test {
    // Error: Abstract constructor.
    abstract public function __construct[private $x];
}
 
interface Test {
    // Error: Abstract constructor.
    public function __construct[private $x];
}
8

Để biết thêm các ví dụ và trường hợp sử dụng, hãy xem biểu thức Khớp v2 RFC và tài liệu PHP

Kiểm tra loại nghiêm ngặt hơn cho toán tử số học/bitwise

Trong các phiên bản PHP trước, cho phép áp dụng các toán tử số học và bitwise cho một mảng, tài nguyên hoặc đối tượng không quá tải. Dù sao, hành vi đôi khi không nhất quán

Trong RFC này, Nikita Popov cho thấy hành vi đó có thể phi lý như thế nào bằng một ví dụ đơn giản

abstract class Test {
    // Error: Abstract constructor.
    abstract public function __construct[private $x];
}
 
interface Test {
    // Error: Abstract constructor.
    public function __construct[private $x];
}
9

Nikita giải thích cách áp dụng toán tử số học hoặc bitwise cho mảng, tài nguyên hoặc đối tượng không quá tải dẫn đến các kết quả khác nhau

Toán tử +, -, *, /, **

  • Ném ngoại lệ Lỗi trên toán hạng mảng. [Không bao gồm + nếu cả hai toán hạng là mảng. ]
  • Âm thầm chuyển đổi toán hạng tài nguyên thành ID tài nguyên dưới dạng số nguyên
  • Chuyển đổi một toán hạng đối tượng thành một số nguyên, trong khi ném một thông báo

Operators %, , &, |, ^:

  • Âm thầm chuyển đổi một toán hạng mảng thành số nguyên 0 nếu trống hoặc số nguyên 1 nếu không trống
  • Âm thầm chuyển đổi toán hạng tài nguyên thành ID tài nguyên dưới dạng số nguyên
  • Chuyển đổi một toán hạng đối tượng thành một số nguyên, trong khi ném một thông báo

Người điều hành ~

  • Ném một ngoại lệ Lỗi cho toán hạng mảng, tài nguyên và đối tượng

Toán tử ++ và –

  • Im lặng không làm gì nếu toán hạng là một mảng, tài nguyên hoặc đối tượng

Với PHP 8, mọi thứ thay đổi và hành vi giống nhau đối với tất cả các toán tử số học và bitwise

Ném một ngoại lệ

class Test {
    // Error: "var" keyword is not supported.
    public function __construct[var $prop] {}
}
9 cho toán hạng mảng, tài nguyên và đối tượng

Các hàm PHP mới

PHP 8 mang đến một số chức năng mới cho ngôn ngữ

str_contains

Trước PHP 8, strstr và strpos là các tùy chọn điển hình để các nhà phát triển tìm kiếm một cây kim bên trong một chuỗi nhất định. Vấn đề là cả hai chức năng không được coi là rất trực quan và việc sử dụng chúng có thể gây nhầm lẫn cho các nhà phát triển PHP mới. Xem ví dụ sau

class Test {
    // Error: Using null default on non-nullable property
    public function __construct[public Type $prop = null] {}

    // Correct: Make the type explicitly nullable instead
    public function __construct[public ?Type $prop = null] {}
}
0

Trong ví dụ trên, chúng tôi đã sử dụng toán tử so sánh

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
17 để kiểm tra xem hai giá trị có cùng loại không. Điều này giúp chúng tôi không gặp lỗi nếu vị trí của kim là 0

“Hàm này có thể trả về giá trị Boolean FALSE, nhưng cũng có thể trả về giá trị không phải Boolean đánh giá là FALSE. […] Sử dụng toán tử === để kiểm tra giá trị trả về của hàm này. ”

Hơn nữa, một số framework cung cấp các hàm trợ giúp để tìm kiếm một giá trị bên trong một chuỗi nhất định [xem ví dụ về tài liệu Trình trợ giúp của Laravel]

Bây giờ, RFC này đề xuất giới thiệu một chức năng mới cho phép tìm kiếm bên trong một chuỗi.

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
18

class Test {
    // Error: Using null default on non-nullable property
    public function __construct[public Type $prop = null] {}

    // Correct: Make the type explicitly nullable instead
    public function __construct[public ?Type $prop = null] {}
}
1

Cách sử dụng của nó khá đơn giản.

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
18 kiểm tra nếu tìm thấy
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
20 trong
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
21 và trả về
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
22 hoặc
class Test {
    // Error: "var" keyword is not supported.
    public function __construct[var $prop] {}
}
7 tương ứng

Vì vậy, nhờ có

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
18, chúng ta có thể viết đoạn mã sau

class Test {
    // Error: Using null default on non-nullable property
    public function __construct[public Type $prop = null] {}

    // Correct: Make the type explicitly nullable instead
    public function __construct[public ?Type $prop = null] {}
}
2

Cái nào dễ đọc hơn và ít bị lỗi hơn [xem mã này đang hoạt động tại đây].
Tại thời điểm viết bài này,

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
18 phân biệt chữ hoa chữ thường, nhưng điều này có thể thay đổi trong tương lai.

Đề xuất

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
18 được thông qua với số phiếu từ 43 đến 9

str_starts_with[] và str_ends_with[]

Ngoài chức năng

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
18, hai chức năng mới cho phép tìm kiếm một cây kim bên trong một chuỗi nhất định.
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
28 và
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
29

Các hàm mới này kiểm tra xem một chuỗi đã cho bắt đầu hay kết thúc bằng một chuỗi khác

class Test {
    // Error: Using null default on non-nullable property
    public function __construct[public Type $prop = null] {}

    // Correct: Make the type explicitly nullable instead
    public function __construct[public ?Type $prop = null] {}
}
3

Cả hai hàm đều trả về

class Test {
    // Error: "var" keyword is not supported.
    public function __construct[var $prop] {}
}
7 nếu
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
20 dài hơn
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
21

Theo Will Hudgins, tác giả của RFC này,

“Chức năng

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
28 và
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
29 thường cần thiết đến mức nhiều khung công tác PHP chính hỗ trợ nó, bao gồm Symfony, Laravel, Yii, FuelPHP và Phalcon. ”

Nhờ chúng, giờ đây chúng tôi có thể tránh sử dụng các hàm dưới mức tối ưu và ít trực quan hơn như

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
35,
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
36. Cả hai hàm đều phân biệt chữ hoa chữ thường

class Test {
    // Error: Using null default on non-nullable property
    public function __construct[public Type $prop = null] {}

    // Correct: Make the type explicitly nullable instead
    public function __construct[public ?Type $prop = null] {}
}
4

Bạn có thể thấy mã này đang hoạt động ở đây

RFC này đã được phê duyệt với 51 đến 4 phiếu bầu

get_debug_type

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
37 là một hàm PHP mới trả về kiểu của một biến. Hàm mới hoạt động theo cách tương tự như hàm
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
38, nhưng
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
37 trả về tên kiểu gốc và giải quyết tên lớp

Đó là một cải tiến tốt cho ngôn ngữ, vì

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
40 không hữu ích cho việc kiểm tra loại

RFC cung cấp hai ví dụ hữu ích để hiểu sự khác biệt giữa hàm

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
41 mới và hàm
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
40. Ví dụ đầu tiên cho thấy
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
38 tại nơi làm việc

class Test {
    // Error: Using null default on non-nullable property
    public function __construct[public Type $prop = null] {}

    // Correct: Make the type explicitly nullable instead
    public function __construct[public ?Type $prop = null] {}
}
5

Với PHP 8, chúng ta có thể sử dụng

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
37, thay vào đó

class Test {
    // Error: Using null default on non-nullable property
    public function __construct[public Type $prop = null] {}

    // Correct: Make the type explicitly nullable instead
    public function __construct[public ?Type $prop = null] {}
}
6

Bảng sau đây hiển thị các giá trị trả về của

class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
37 và
class Point {
    public function __construct[
        public int $x = 0,
        public int $y = 0,
        public int $z = 0,
    ] {}
}
38

Valuegettype[]get_debug_type[]1integerint0. 1doublefloattruebooleanboolfalsebooleanboolnullNULLnull“WordPress”stringstring[1,2,3]arrayarrayMột lớp có tên “Foo\Bar”đối tượngFoo\BarMột đối tượng lớp ẩn danh[email được bảo vệ]

RFC bổ sung

Dưới đây là danh sách nhanh các cải tiến bổ sung đã được phê duyệt đi kèm với PHP 8

  1. Giao diện có thể xâu chuỗi. RFC này giới thiệu giao diện Stringable được tự động thêm vào các lớp triển khai phương thức
    class Point {
        public function __construct[
            public int $x = 0,
            public int $y = 0,
            public int $z = 0,
        ] {}
    }
    47. Mục tiêu chính ở đây là sử dụng loại công đoàn
    class Point {
        public function __construct[
            public int $x = 0,
            public int $y = 0,
            public int $z = 0,
        ] {}
    }
    48
  2. DOM Living Standard API mới trong ext/dom. RFC này đề xuất triển khai DOM Living Standard hiện tại cho phần mở rộng PHP DOM bằng cách giới thiệu các giao diện và thuộc tính công khai mới
  3. Kiểu trả về tĩnh. PHP 8 giới thiệu cách sử dụng
    class Point {
        public function __construct[
            public int $x = 0,
            public int $y = 0,
            public int $z = 0,
        ] {}
    }
    49 làm kiểu trả về bên cạnh kiểu
    class Point {
        public function __construct[
            public int $x = 0,
            public int $y = 0,
            public int $z = 0,
        ] {}
    }
    50 và
    class Point {
        public function __construct[
            public int $x = 0,
            public int $y = 0,
            public int $z = 0,
        ] {}
    }
    51
  4. Chỉnh sửa cú pháp biến. RFC này giải quyết một số mâu thuẫn còn lại trong cú pháp biến của PHP

Điểm chuẩn hiệu suất PHP 8

Nếu bạn đang thắc mắc PHP 8 nhanh như thế nào, chúng tôi có câu trả lời. Chúng tôi đã đo điểm chuẩn cho 20 nền tảng/cấu hình PHP trên 7 phiên bản PHP khác nhau [5. 6, 7. 0, 7. 1, 7. 2, 7. 3 và 8. 0]

PHP8. 0 nổi lên như người chiến thắng trong hầu hết các nền tảng hỗ trợ nó, bao gồm cả WordPress và Laravel

Tổng hợp điểm chuẩn PHP của các nền tảng hàng đầu

Chẳng hạn, WordPress trên PHP 8. 0 có thể xử lý 18. Nhiều hơn 4% yêu cầu mỗi giây so với PHP 7. 4. Tương tự như vậy, Laravel trên PHP 8. 0 có thể chạy 8. Nhiều hơn 5% yêu cầu mỗi giây so với PHP 7. 3

Nếu trang web hoặc ứng dụng của bạn hoàn toàn tương thích với PHP 8. 0, bạn nên lập kế hoạch cập nhật môi trường máy chủ của mình lên PHP 8. 0 càng sớm càng tốt. Bạn [và người dùng của bạn] chắc chắn sẽ đánh giá cao những lợi ích về hiệu suất của nó. Tuy nhiên, vui lòng kiểm tra trang web của bạn kỹ lưỡng trước khi cập nhật

Bạn có thể đọc bài viết điểm chuẩn PHP của chúng tôi để biết thêm thông tin, chẳng hạn như dữ liệu hiệu suất chi tiết, thông tin chi tiết và biểu đồ đẹp

PHP 8 đã được phát hành cho GA và mang lại nhiều tính năng và tối ưu hóa cho ngôn ngữ này. 🚀 Hãy xem phần đi sâu của chúng tôi vào PHP 8. Nhấp để Tweet

Bản tóm tắt

Thật là một chuyến đi. Trong bài đăng này, chúng tôi đã đề cập đến các tính năng và tối ưu hóa thú vị nhất đi kèm với PHP 8. Điều được chờ đợi nhất chắc chắn là trình biên dịch Just in Time, nhưng còn nhiều hơn thế nữa với PHP 8

Đảm bảo đánh dấu bài đăng trên blog này để bạn tham khảo trong tương lai. 🤓

Bây giờ đến lượt của bạn. bạn đã sẵn sàng thử nghiệm các tính năng mới của PHP chưa?

Nhận tất cả các ứng dụng, cơ sở dữ liệu và trang web WordPress của bạn trực tuyến và dưới một mái nhà. Nền tảng đám mây hiệu suất cao, đầy đủ tính năng của chúng tôi bao gồm

  • Dễ dàng thiết lập và quản lý trong bảng điều khiển MyKinsta
  • Hỗ trợ chuyên gia 24/7
  • Mạng và phần cứng Google Cloud Platform tốt nhất, được cung cấp bởi Kubernetes để có khả năng mở rộng tối đa
  • Tích hợp Cloudflare cấp doanh nghiệp cho tốc độ và bảo mật
  • Tiếp cận đối tượng toàn cầu với tối đa 35 trung tâm dữ liệu và hơn 275 PoP trên toàn thế giới

Hãy tự kiểm tra với $20 trong tháng đầu tiên của Lưu trữ ứng dụng hoặc Lưu trữ cơ sở dữ liệu. Khám phá kế hoạch của chúng tôi hoặc nói chuyện với bộ phận bán hàng để tìm thấy sự phù hợp nhất của bạn

Sự khác biệt giữa PHP 7 và PHP 8 là gì?

Nhóm đằng sau việc phát hành PHP 8 tự hào về thông báo của họ về hiệu suất tốt hơn, cú pháp tốt hơn và an toàn loại được cải thiện. PHP 8 nhanh hơn PHP 7, cú pháp yêu cầu ít mã hơn và hỗ trợ gõ tốt hơn . Ba loại cải tiến này cung cấp một bản phát hành phiên bản chính mạnh mẽ của PHP.

Có gì mới trong PHP 7 và 8?

Nó chứa nhiều tính năng và tối ưu hóa mới bao gồm các đối số được đặt tên, các loại liên kết, thuộc tính, quảng cáo thuộc tính hàm tạo, biểu thức khớp, toán tử nullsafe, JIT và các cải tiến trong hệ thống loại, xử lý lỗi và tính nhất quán

PHP 8 có nhanh hơn PHP 7 không?

PHP 8 sẽ nhanh hơn nhiều so với PHP 7 do thiết kế không đồng bộ mới và trình biên dịch JIT, bạn sẽ có thể xây dựng các ứng dụng không đồng bộ trong PHP 8, đây là một vấn đề lớn đối với .

Các tính năng mới trong PHP 8 là gì?

Các cải tiến và tính năng mới của PHP 8 .
Khuyến mãi bất động sản xây dựng
Xác thực cho các phương thức đặc điểm trừu tượng
Chữ ký phương thức không tương thích
Mảng bắt đầu với một chỉ số tiêu cực
Liên minh loại 2. 0
Lỗi loại nhất quán cho các chức năng nội bộ
ném biểu thức
Bản đồ yếu

Chủ Đề