Làm cách nào để kiểm tra xem một biến có chưa được khởi tạo trong PHP không?

Trong các ngôn ngữ như C và C++, hầu hết các phương pháp giảng dạy sẽ khiến bạn phải suy nghĩ về việc tạo các biến theo hai giai đoạn riêng biệt. Đầu tiên, bạn sẽ khai báo biến

int c;

và sau đó bạn sẽ khởi tạo biến với giá trị mặc định của nó

c = 42

Khi bạn khai báo biến, bạn sẽ cho trình biên dịch biết loại giá trị mà biến sẽ lưu trữ. Khi bạn khởi tạo biến, bạn sẽ cho trình biên dịch biết giá trị ban đầu/mặc định của biến đó là bao nhiêu

Điều này rất quan trọng trong các ngôn ngữ như C và C++ vì các ngôn ngữ này thiên về suy nghĩ về các biến như nội dung của bộ nhớ tại một địa chỉ cụ thể (so với suy nghĩ về các biến như giá trị mà chúng nắm giữ). Nếu bạn đã khai báo một biến mà không khởi tạo nó, chương trình của bạn sẽ trả về giá trị xảy ra tại một địa chỉ bộ nhớ cụ thể. Bộ nhớ có thể chứa bất cứ thứ gì và không xác định giữa các lần chạy chương trình. Bạn sẽ thường nghe những thứ này được gọi là "giá trị rác" vì đây thường không phải là hành vi bạn muốn

Khi các ngôn ngữ thế hệ tiếp theo xuất hiện, (Java, C#, python, PHP, v.v. ) một trong những vấn đề họ muốn giải quyết là khoảng cách giữa khai báo và khởi tạo. Hầu hết các ngôn ngữ của thời đại này thực hiện một số hình thức khởi tạo giá trị mặc định tự động. Nếu một lập trình viên người dùng cuối không bao gồm giá trị ban đầu cho một biến, thì chương trình sẽ sử dụng một giá trị như null, None, undefined, v.v.

Mặc dù hành vi này đi kèm với các vấn đề riêng của nó (Gọi hàm thành viên trên một đối tượng không phải là đối tượng,

c = 42
0, v.v. ), các vấn đề ít nhất là nhất quán. Lo lắng về bộ nhớ rác không phải là điều bạn sẽ làm thường xuyên nếu bạn đang làm việc với các ngôn ngữ này

Thuộc tính gõ PHP

Các ngôn ngữ PHP cốt lõi tiếp tục bổ sung các tính năng từ các ngôn ngữ được gõ mạnh hơn. Một tính năng gần đây, được giới thiệu trong PHP 7. 4, là thuộc tính lớp gõ. Điều này cho phép bạn thêm các loại vào thuộc tính lớp của mình như thế này

bar = "Hello World";
$object->baz = "Hello World";

// these two lines are not OK, because
// an int or an object is not a string
$object->bar = 123;
$object->baz = new Baz;

// this is allowed, because the `?` in `string?`
// means "allow null values"
$object->baz = null;

// this is not allowed, because without the `?` a values of
// null is NOT allowed
$object->bar = null;

Trong chương trình trên, đối tượng

c = 42
1 được lưu trữ trong
c = 42
2 có thuộc tính
c = 42
3 và thuộc tính
c = 42
4. Vì những thuộc tính đó được tạo với loại
c = 42
5

public string $bar;
public ?string $baz;

lập trình viên người dùng cuối sẽ không thể gán giá trị cho chúng không phải là chuỗi. Một ngoại lệ cho điều này là loại

c = 42
5 bao gồm một
c = 42
7 ở đầu. Đây là loại "nullable" và có nghĩa là chúng tôi được phép gán giá trị null cho thuộc tính

Khả năng cho biết liệu null có được phép hay không đối với một thuộc tính là một tính năng không có sẵn, theo mặc định, trong nhiều ngôn ngữ hướng đối tượng truyền thống. Ưu điểm của loại không thể vô hiệu hóa là bạn tránh được cả một loại lỗi (Gọi hàm thành viên trên một đối tượng không phải là đối tượng,

c = 42
0, v.v. )

Tuy nhiên, giống như nhiều tính năng mới, chúng tôi đã đánh đổi vấn đề này để lấy vấn đề khác

Giá trị mặc định cho các loại không nullable

Bài kiểm tra nhỏ bất ngờ. Nếu bạn có mã giống như thế này, giá trị nào sẽ bị loại bỏ?

zap
);

Ở đây chúng ta thấy khoảng cách giữa khai báo và khởi tạo đã trở lại. Chúng tôi đã khai báo thuộc tính

bar = "Hello World";
$object->baz = "Hello World";

// these two lines are not OK, because
// an int or an object is not a string
$object->bar = 123;
$object->baz = new Baz;

// this is allowed, because the `?` in `string?`
// means "allow null values"
$object->baz = null;

// this is not allowed, because without the `?` a values of
// null is NOT allowed
$object->bar = null;
1 và nói với PHP rằng
bar = "Hello World";
$object->baz = "Hello World";

// these two lines are not OK, because
// an int or an object is not a string
$object->bar = 123;
$object->baz = new Baz;

// this is allowed, because the `?` in `string?`
// means "allow null values"
$object->baz = null;

// this is not allowed, because without the `?` a values of
// null is NOT allowed
$object->bar = null;
2 phải chứa một đối tượng có loại là
bar = "Hello World";
$object->baz = "Hello World";

// these two lines are not OK, because
// an int or an object is not a string
$object->bar = 123;
$object->baz = new Baz;

// this is allowed, because the `?` in `string?`
// means "allow null values"
$object->baz = null;

// this is not allowed, because without the `?` a values of
// null is NOT allowed
$object->bar = null;
3. Nếu đây là một biến PHP không được nhập kiểu truyền thống, thì PHP sẽ tự động gán giá trị null cho
bar = "Hello World";
$object->baz = "Hello World";

// these two lines are not OK, because
// an int or an object is not a string
$object->bar = 123;
$object->baz = new Baz;

// this is allowed, because the `?` in `string?`
// means "allow null values"
$object->baz = null;

// this is not allowed, because without the `?` a values of
// null is NOT allowed
$object->bar = null;
5. Tuy nhiên, hệ thống loại nghiêm cấm điều này

Về lý thuyết, các thành viên cốt lõi của nhóm PHP có thể đã cố gắng ngôn ngữ để tự động khai báo một biến

bar = "Hello World";
$object->baz = "Hello World";

// these two lines are not OK, because
// an int or an object is not a string
$object->bar = 123;
$object->baz = new Baz;

// this is allowed, because the `?` in `string?`
// means "allow null values"
$object->baz = null;

// this is not allowed, because without the `?` a values of
// null is NOT allowed
$object->bar = null;
3 “trống” — nhưng nếu lớp
bar = "Hello World";
$object->baz = "Hello World";

// these two lines are not OK, because
// an int or an object is not a string
$object->bar = 123;
$object->baz = new Baz;

// this is allowed, because the `?` in `string?`
// means "allow null values"
$object->baz = null;

// this is not allowed, because without the `?` a values of
// null is NOT allowed
$object->bar = null;
3 của chúng ta trông như thế này thì sao?

class Zap {
    public function __construct(A $a, B $b, C $c, /* .. */) {
    }
}

PHP nên lấy các giá trị theo yêu cầu của hàm tạo của

bar = "Hello World";
$object->baz = "Hello World";

// these two lines are not OK, because
// an int or an object is not a string
$object->bar = 123;
$object->baz = new Baz;

// this is allowed, because the `?` in `string?`
// means "allow null values"
$object->baz = null;

// this is not allowed, because without the `?` a values of
// null is NOT allowed
$object->bar = null;
3 ở đâu?

Vậy PHP đã giải quyết vấn đề này như thế nào?

PHP Fatal error:  Uncaught Error: Typed property Zip::$zap must not be accessed before
                  initialization in /private/tmp/test.php:10
Stack trace:
#0 {main}
  thrown in /private/tmp/test.php on line 10

Đó là — PHP sẽ gặp sự cố với một lỗi nghiêm trọng nếu bạn cố gắng truy cập thuộc tính

bar = "Hello World";
$object->baz = "Hello World";

// these two lines are not OK, because
// an int or an object is not a string
$object->bar = 123;
$object->baz = new Baz;

// this is allowed, because the `?` in `string?`
// means "allow null values"
$object->baz = null;

// this is not allowed, because without the `?` a values of
// null is NOT allowed
$object->bar = null;
5 trước khi nó được gán — tôi. e. được khởi tạo với — một giá trị

PHP so với. Ngôn ngữ được biên dịch thủ công

Lần đầu tiên tôi nhìn thấy hành vi này — một ngôn ngữ từ chối cho phép truy cập vào một giá trị được đơn vị hóa — trong Rust. Rust có một lợi thế bổ sung so với PHP ở đây và đó là bước biên dịch thủ công. Rust sẽ từ chối biên dịch chương trình nếu bạn cố truy cập vào một biến chưa được khởi tạo. Điều này có nghĩa là không thể triển khai một chương trình rỉ sét với mã truy cập vào một biến chưa được khởi tạo

Mặt khác, PHP không có trình biên dịch. Điều này có nghĩa là những kiểm tra này đang diễn ra trong thời gian chạy, nghĩa là những lỗi này sẽ không xuất hiện cho đến khi bạn thực sự triển khai chương trình của mình. Đúng là trong các ví dụ đơn giản mà chúng ta đã nói về những vấn đề này sẽ xuất hiện trong quá trình phát triển — tuy nhiên, trong một chương trình không tầm thường, rất dễ tạo ra một lỗi phụ thuộc vào dữ liệu và sẽ không xuất hiện cho đến khi nó được triển khai

Trong các ngôn ngữ được biên dịch thủ công, hệ thống loại ngăn chặn loại lỗi này. Trong các ngôn ngữ không được biên dịch thủ công, hệ thống loại không ngăn chặn loại lỗi này

Nhưng đợi đã. Còn phân tích tĩnh như phpstan hay Psalm thì sao?

Mặc dù PHP 5. 0 lần đầu tiên thêm gợi ý loại vào ngôn ngữ 17 năm trước, tính an toàn của loại PHP vẫn được mô tả tốt hơn là an toàn. Kết quả cuối cùng là một ngôn ngữ mà các chuyên gia PHP được trang bị tốt hơn để cung cấp mã ổn định, nhưng nơi mà người có sở thích, người dùng thông thường hoặc chuyên gia đa ngôn ngữ phải đối mặt với đường cong học tập ngày càng dốc và các chương trình khó lý giải hơn

Làm cách nào để kiểm tra xem biến có chưa được xác định trong PHP không?

$isTouch = isset($variable); Nó sẽ trả về true nếu biến $ được xác định. Nếu biến không được xác định, nó sẽ trả về false. Ghi chú. Nó trả về TRUE nếu biến tồn tại và có giá trị khác NULL, FALSE nếu không.

Làm cách nào để kiểm tra xem biến có trống trong PHP không?

Hàm PHP empty() . Hàm này trả về false nếu biến tồn tại và không rỗng, ngược lại trả về true. Các giá trị sau ước tính trống. 0.

Làm cách nào để kiểm tra xem biến có phải là NULL trong PHP không?

Hàm is_null() kiểm tra xem một biến có phải là NULL hay không. Hàm này trả về true (1) nếu biến là NULL, ngược lại trả về false/nothing.

Giá trị của biến chưa được khởi tạo trong PHP là gì?

Các biến chưa được khởi tạo có giá trị mặc định của loại của chúng tùy thuộc vào ngữ cảnh mà chúng được sử dụng - booleans mặc định là false , số nguyên và số thực mặc định là 0, chuỗi (e. g. được sử dụng trong tiếng vang) được đặt thành một chuỗi rỗng và các mảng trở thành một mảng trống .