PHP7. 4 cuối cùng mang thuộc tính gõ. Đây là một tính năng mà tôi đã mong đợi và tôi đã dành thời gian chất lượng để làm việc với các dự án hiện tại của mình để thêm hỗ trợ cho các thuộc tính đã nhập
Với các thuộc tính đã nhập, bạn có thể đặt một loại cho tất cả các thuộc tính của lớp. Khi một loại được đặt, công cụ PHP sẽ ngăn mọi người đặt một loại khác cho thuộc tính lớp
class Example {
public string $name;
public DateTime $birthday;
}
Đoạn mã trên sẽ đảm bảo rằng thuộc tính
class Example {
public $name;
}
$foo = new Example[];
var_dump[$foo->name === null]; // true
7 sẽ luôn là đối tượng class Example {
public $name;
}
$foo = new Example[];
var_dump[$foo->name === null]; // true
8. Trước PHP 7. 4, loại mẫu dữ liệu nghiêm ngặt này sẽ yêu cầu phải có các phương thức class Example {
public $name;
}
$foo = new Example[];
var_dump[$foo->name === null]; // true
9 và class Example {
public string $name;
}
$foo = new Example[];
var_dump[$foo->name === null];
0 để thực thi tính toàn vẹn của dữ liệuCác loại thuộc tính được hỗ trợ
Các loại được hỗ trợ cho thuộc tính lớp- các loại vô hướng.
1,class Example { public string $name; } $foo = new Example[]; var_dump[$foo->name === null];
2,class Example { public string $name; } $foo = new Example[]; var_dump[$foo->name === null];
3 vàclass Example { public string $name; } $foo = new Example[]; var_dump[$foo->name === null];
4class Example { public string $name; } $foo = new Example[]; var_dump[$foo->name === null];
- các loại hợp chất.
5,class Example { public string $name; } $foo = new Example[]; var_dump[$foo->name === null];
6 vàclass Example { public string $name; } $foo = new Example[]; var_dump[$foo->name === null];
7class Example { public string $name; } $foo = new Example[]; var_dump[$foo->name === null];
- Bất kỳ tên lớp hoặc giao diện nào [chẳng hạn như
8,class Example { public $name; } $foo = new Example[]; var_dump[$foo->name === null]; // true
9] vàclass Example { public string $name; } $foo = new Example[]; var_dump[$foo->name === null];
0Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
- Tham chiếu đến các đối tượng cha mẹ và sở hữu.
1 vàFatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
2Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
3. Có một tài sảnFatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
3 sẽ không có ý nghĩaFatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
5. Không được hỗ trợ vì hành vi của nó là không thể đoán trước. Hãy xem RFC có thể gọi nhất quán để biết thêm thông tin cơ bản. Về cơ bản, điều này trở nên rắc rối khi các cuộc gọi có thể được khai báo bằng cú pháp mảng, e. g. nhưFatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
6Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
Đây sẽ là nơi hầu hết các hành vi giật tóc có thể xảy ra. Với PHP7. 4 thuộc tính đã nhập, thuộc tính lớp có trạng thái chưa được khởi tạo. Điều này đơn giản có nghĩa là thuộc tính chưa được khởi tạo. Điều này không giống với
Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
8Nếu không có loại nào được khai báo, các thuộc tính có giá trị chưa khởi tạo là
Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
8class Example {
public $name;
}
$foo = new Example[];
var_dump[$foo->name === null]; // true
Khi một loại được khai báo, tất cả các thuộc tính sẽ có trạng thái chưa được khởi tạo. Không được phép truy cập các thuộc tính của lớp trước khi gán giá trị rõ ràng
class Example {
public string $name;
}
$foo = new Example[];
var_dump[$foo->name === null];
Trong đoạn trích này, thuộc tính
class Example {
public ?string $name;
}
$foo = new Example[];
$foo->name = 'Ayesh'; // Valid
$foo->name = null; // Valid
0 chưa được khởi tạo. Điều này không giống với Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
8 và đoạn mã trên sẽ báo lỗiFatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
Kiểm tra trạng thái chưa khởi tạo
Bạn có thể kiểm tra xem một thuộc tính lớp có chưa được khởi tạo hay không bằng cách sử dụng
class Example {
public ?string $name;
}
$foo = new Example[];
$foo->name = 'Ayesh'; // Valid
$foo->name = null; // Valid
2. Vì giá trị này không giống với Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
8 nên bạn không thể sử dụng class Example {
public ?string $name;
}
$foo = new Example[];
$foo->name = 'Ayesh'; // Valid
$foo->name = null; // Valid
4 để kiểm tra xem thuộc tính có chưa được khởi tạo hay khôngĐặt lại thuộc tính về trạng thái chưa khởi tạo
Để đặt lại thuộc tính về trạng thái chưa khởi tạo, hãy sử dụng
class Example {
public ?string $name;
}
$foo = new Example[];
$foo->name = 'Ayesh'; // Valid
$foo->name = null; // Valid
5. Sau khi không được đặt, cố gắng truy cập vào thuộc tính mà không gán giá trị cho thuộc tính đó sẽ gây ra lỗi class Example {
public ?string $name;
}
$foo = new Example[];
$foo->name = 'Ayesh'; // Valid
$foo->name = null; // Valid
6 tương tựloại nullable
Tương tự với PHP7. 1 loại có thể vô giá trị, các loại thuộc tính cũng có thể được đánh dấu là có thể vô giá trị. Để đánh dấu một thuộc tính có thể là null, hãy đặt trước loại của nó một dấu chấm hỏi, e. g.
class Example {
public ?string $name;
}
$foo = new Example[];
$foo->name = 'Ayesh'; // Valid
$foo->name = null; // Valid
7class Example {
public ?string $name;
}
$foo = new Example[];
$foo->name = 'Ayesh'; // Valid
$foo->name = null; // Valid
Ngay cả khi một thuộc tính được đánh dấu là nullable, thì giá trị chưa được khởi tạo của nó sẽ không
Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
8. Ví dụ: đoạn mã bên dưới vẫn sẽ báo lỗiclass Example {
public ?string $name;
}
$foo = new Example[];
var_dump[$foo->name];
// Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization
Mặc dù điều này có vẻ rườm rà khi làm việc, nhưng điều này cung cấp một tính năng tuyệt vời mà bạn có thể chắc chắn rằng thuộc tính lớp sẽ luôn thuộc loại đó. Nếu giá trị không được khởi tạo, PHP sẽ từ bỏ và đưa ra một lỗi thay vì trả về
Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
8, giống như đối với các thuộc tính chưa được nhậploại nghiêm ngặt
Các thuộc tính của lớp cũng hỗ trợ khai báo kiểu nghiêm ngặt với
class Example {
public ?string $name;
}
$foo = new Example[];
var_dump[$foo->name];
// Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization
0 ở đầu khối PHP của tệp. Nếu không có các loại nghiêm ngặt, PHP sẽ chuyển các giá trị thành loại thuộc tínhclass Example {
public string $name;
}
$foo = new Example[];
$foo->name = 420;
var_dump[$foo->name];
// string[3] "420"
Lưu ý cách chúng tôi đặt một
class Example {
public ?string $name;
}
$foo = new Example[];
var_dump[$foo->name];
// Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization
1 cho thuộc tính class Example {
public string $name;
}
$foo = new Example[];
var_dump[$foo->name === null];
2 và cuộc gọi class Example {
public ?string $name;
}
$foo = new Example[];
var_dump[$foo->name];
// Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization
3 trả về class Example {
public ?string $name;
}
$foo = new Example[];
var_dump[$foo->name];
// Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization
4 dưới dạng một class Example {
public string $name;
}
$foo = new Example[];
var_dump[$foo->name === null];
2. Khi gán giá trị, công cụ sẽ truyền giá trị cho loại đã khai báoĐể giảm thiểu các vấn đề với việc sắp xếp kiểu và để tận dụng tối đa các thuộc tính được nhập, tôi khuyên bạn nên kiểm tra các lớp của mình với
class Example {
public ?string $name;
}
$foo = new Example[];
var_dump[$foo->name];
// Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization
0. Rất dễ bỏ qua khi PHP hữu ích khi nó chuyển sang một loại cho bạn, nhưng đây có thể là gốc rễ của một số lỗi ở hạ lưu. Dễ dàng gỡ lỗi một lỗi xuất hiện ngay lập tức hơn là một lỗi chỉ xảy ra vào tối thứ Sáu lúc 6 giờ. 28PM, chỉ khi DST có hiệu lựcThuộc tính tĩnh và tham chiếu
Thuộc tính tĩnh cũng có thể có các loại được khai báo. Điều này có vẻ như là một chi tiết rõ ràng, nhưng các đề xuất trước đây cho các thuộc tính đã nhập không bao gồm các thuộc tính tĩnh. Trong PHP7. 4, bạn cũng có thể khai báo các kiểu cho thuộc tính tĩnh
Hơn nữa, bạn có thể trả lại một tham chiếu đến một thuộc tính đã nhập và các loại sẽ vẫn được vinh danh
class Example {
public string $name;
}
$foo = new Example[];
$foo->name = 'Apple';
$bar =& $foo->name;
$bar = []; // Not allowed
Điều này sẽ ném một lỗi
Fatal error: Uncaught TypeError: Cannot assign .. to reference held by property Example::$name of type .. in ...
Giá trị mặc định trong hàm tạo và khai báo thuộc tính
Vì lý do lịch sử, PHP cho phép bạn đặt giá trị mặc định cho các đối số hàm trong phần khai báo của nó ngay cả khi loại không thể rỗng
class Example {
public function __construct[string $name = null] {
var_dump[$name];
}
}
$foo = new Example[];
// NULL
Trong hàm tạo, chúng tôi đánh dấu rõ ràng rằng đối số
class Example {
public ?string $name;
}
$foo = new Example[];
$foo->name = 'Ayesh'; // Valid
$foo->name = null; // Valid
0 không thể rỗng và PHP chấp nhận Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
8 làm giá trị mặc định. Hành vi này chỉ áp dụng cho các giá trị mặc định của Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
8. Mặc dù điều này không hợp lệ về mặt ngữ nghĩa, hành vi này được cho phép vì lý do lịch sử và triển khaiVới các thuộc tính đã nhập, điều này không được phép
class Example {
public $name;
}
$foo = new Example[];
var_dump[$foo->name === null]; // true
0Điều này sẽ nhanh chóng đưa ra một lỗi
class Example {
public $name;
}
$foo = new Example[];
var_dump[$foo->name === null]; // true
1Loại phương sai
PHP7. 4 đi kèm với phương sai kiểu trả về, có nghĩa là một lớp con có thể trả về một thể hiện cụ thể hơn. Điều này chưa được hỗ trợ cho các loại tài sản. Ví dụ
class Example {
public $name;
}
$foo = new Example[];
var_dump[$foo->name === null]; // true
2Mã ở trên sẽ không hoạt động. Mặc dù
class Example {
public string $name;
}
$foo = new Example[];
$foo->name = 420;
var_dump[$foo->name];
// string[3] "420"
0 là tập con của lớp class Example {
public string $name;
}
$foo = new Example[];
$foo->name = 420;
var_dump[$foo->name];
// string[3] "420"
1 nhưng không được phép thay đổi khai báo kiểu của class Example {
public string $name;
}
$foo = new Example[];
$foo->name = 420;
var_dump[$foo->name];
// string[3] "420"
2. Bạn vẫn có thể gán phiên bản của class Example {
public string $name;
}
$foo = new Example[];
$foo->name = 420;
var_dump[$foo->name];
// string[3] "420"
1 cho class Example {
public string $name;
}
$foo = new Example[];
$foo->name = 420;
var_dump[$foo->name];
// string[3] "420"
2. Cái này được gọi là class Example {
public string $name;
}
$foo = new Example[];
$foo->name = 420;
var_dump[$foo->name];
// string[3] "420"
5 và hiện được hỗ trợ cho các loại trả lạiThử ở trên sẽ đưa ra một lỗi như sau
class Example {
public $name;
}
$foo = new Example[];
var_dump[$foo->name === null]; // true
3Đoạn mã sau vẫn còn hiệu lực
class Example {
public $name;
}
$foo = new Example[];
var_dump[$foo->name === null]; // true
4Lưu ý cách khai báo thuộc tính trong
class Example {
public string $name;
}
$foo = new Example[];
$foo->name = 420;
var_dump[$foo->name];
// string[3] "420"
6 và class Example {
public string $name;
}
$foo = new Example[];
$foo->name = 420;
var_dump[$foo->name];
// string[3] "420"
2 là class Example {
public string $name;
}
$foo = new Example[];
$foo->name = 420;
var_dump[$foo->name];
// string[3] "420"
1, nhưng chúng tôi chỉ định một thể hiện class Example {
public string $name;
}
$foo = new Example[];
$foo->name = 420;
var_dump[$foo->name];
// string[3] "420"
0 cho nóĐể tóm tắt
- Bạn không thể thay thế một lớp con cho tài sản
- Bạn không thể thêm các loại vào các lớp con nếu lớp cha không có các loại được thực thi
- Bạn không thể đánh dấu một loại không nullable là nullable trong một lớp con
- Bạn không thể đánh dấu một loại nullable là không nullable trong một lớp con
Để hình dung điều này, hãy xem chuỗi thừa kế sau. Không ai trong số những điều sau đây được phép
class Example {
public $name;
}
$foo = new Example[];
var_dump[$foo->name === null]; // true
5Ở trên sẽ đưa ra các lỗi sau [không đồng thời]
class Example {
public $name;
}
$foo = new Example[];
var_dump[$foo->name === null]; // true
6Tương thích ngược
Khai báo các loại thuộc tính là tùy chọn và tất cả mã hiện tại của bạn sẽ hoạt động. Nếu bạn dự định nâng cấp một cơ sở mã hiện có thành các thuộc tính đã nhập, hãy để ý đến trạng thái chưa được khởi tạo và kế thừa nơi các quy tắc được thực thi khá nghiêm ngặt. Hơn nữa, các loại thuộc tính không mang hành vi kế thừa cho phép các giá trị
Fatal error: Uncaught Error: Typed property Example::$name must not be accessed before initialization in ...
8 trong các đối số hàm/phương thức của chúng và điều này có thể gây bất ngờSuy nghĩ cuối cùng
Các loại thuộc tính là một tính năng mà cá nhân tôi rất hào hứng và bây giờ cuối cùng nó đã có ở đây, tôi đã dành thời gian để thêm các loại thuộc tính vào các dự án riêng tư hiện có của mình. PHPStorm 2019. 3 đi kèm với sự hỗ trợ cho tất cả PHP 7. 4 và có một cách khắc phục nhanh để thêm các loại thuộc tính nếu nó có thể được thu thập từ các nhận xét về docblock thuộc tính hoặc từ hàm tạo
Ngay cả trong các dự án có phạm vi kiểm tra 100%, tôi vẫn phát hiện ra một số lỗi luôn ở đó, nhưng các loại tài sản đưa chúng lên hàng đầu và trung tâm
Các dự án mã nguồn mở có thể mất chút thời gian để yêu cầu PHP 7. 4 là phiên bản tối thiểu, nhưng điều đó sẽ không ngăn bạn sử dụng chúng trong các dự án riêng tư của mình