Không thể vượt qua đối số null khi sử dụng gợi ý kiểu


190

Các mã sau đây:

<?php

    class Type {

    }

    function foo(Type $t) {

    }

    foo(null);

?>

thất bại trong thời gian chạy:

PHP Fatal error:  Argument 1 passed to foo() must not be null

Tại sao nó không được phép chuyển null giống như các ngôn ngữ khác?

Câu trả lời:


353

PHP 7.1 hoặc mới hơn (phát hành ngày 2 tháng 12 năm 2016)

Bạn có thể khai báo rõ ràng một biến nulltheo cú pháp này

function foo(?Type $t) {
}

điều này sẽ dẫn đến

$this->foo(new Type()); // ok
$this->foo(null); // ok
$this->foo(); // error

Vì vậy, nếu bạn muốn một đối số tùy chọn, bạn có thể tuân theo quy ước Type $t = nulltrong khi nếu bạn cần làm cho một đối số chấp nhận cả hai nullvà loại của nó, bạn có thể làm theo ví dụ trên.

Bạn có thể đọc thêm ở đây .


PHP 7.0 trở lên

Bạn phải thêm một giá trị mặc định như

function foo(Type $t = null) {

}

Bằng cách đó, bạn có thể vượt qua nó một giá trị null.

Điều này được ghi lại trong phần trong tài liệu hướng dẫn về Tuyên bố Loại :

Khai báo có thể được thực hiện để chấp nhận NULLcác giá trị nếu giá trị mặc định của tham số được đặt thành NULL.


10
Vậy tại sao null null đối tượng null ?
Pacerier

4
Hầu hết các ngôn ngữ cho phép null có bất kỳ loại. Trong kịch bản này.
Henry

24
Theo tôi đây là một cấu trúc ngôn ngữ kém. 1. Trong các ngôn ngữ khác, null có khả năng thuộc bất kỳ loại nào, do đó làm cho null trở thành một đối số hợp lệ trong trường hợp này. 2: Php đang sử dụng một giá trị mặc định cho một đối số để chỉ định rằng null được phép, điều này không rõ ràng và nó làm cho một tham số bắt buộc không thể thực hiện được ngay cả khi nhà phát triển muốn buộc null được thông qua rõ ràng.
Henry

2
Tôi đồng ý với @Henry, ngoài ra có vẻ lạ khi yêu cầu các thông số sau khi trông giống như một thông số tùy chọn.
Lực lượng anh hùng

6
Tôi chỉ đồng ý với @Henry vào ngày 2. Về 1 thực tế là bạn không thể chuyển null thành function foo(Type $t)một điều RẤT tốt; xem Tài liệu tham khảo Null: Sai lầm tỷ đô
Constantin Galbenu

35

Bắt đầu từ PHP 7.1, các kiểu nullable đều có sẵn, vì cả hai kiểu trả về hàm và tham số. Loại ?Tcó thể có các giá trị của Loại được chỉ định T, hoặc null.

Vì vậy, chức năng của bạn có thể trông như thế này:

function foo(?Type $t)
{

}

Ngay khi bạn có thể làm việc với PHP 7.1, ký hiệu này sẽ được ưu tiên hơn function foo(Type $t = null)bởi vì nó vẫn buộc người gọi xác định rõ ràng một đối số cho tham số $t.


12

Thử:

function foo(Type $t = null) {

}

Kiểm tra các đối số chức năng PHP .


11
Vấn đề tôi gặp phải là nó thay đổi định nghĩa của hàm. Bây giờ tham số là tùy chọn - không thực sự là những gì tác giả dự định (mặc dù, nếu anh ta chuyển nó thành null, thì nó hoàn toàn là tùy chọn).
nghiền nát

7

Như các câu trả lời khác đã được đề cập, điều này chỉ có thể nếu bạn chỉ định nulllàm giá trị mặc định.

Nhưng giải pháp hướng đối tượng an toàn loại sạch nhất sẽ là NullObject :

interface FooInterface
{
    function bar();
}
class Foo implements FooInterface
{
    public function bar()
    {
        return 'i am an object';
    }
}
class NullFoo implements FooInterface
{
    public function bar()
    {
        return 'i am null (but you still can use my interface)';
    }
}

Sử dụng:

function bar_my_foo(FooInterface $foo)
{
    if ($foo instanceof NullFoo) {
        // special handling of null values may go here
    }
    echo $foo->bar();
}

bar_my_foo(new NullFoo);

1
Cách tiếp cận này thường không thực tế, vì thay vì 1 lớp, bây giờ bạn cần 3. Ngoài ra, nó buộc người viết NullFoophải ghi đè các phương thức trừu tượng, mặc dù chúng không có ý nghĩa (theo định nghĩa null).
TheOperator

1
Theo kinh nghiệm của tôi, mẫu NullObject có thể thực tế, nếu bạn làm việc nói chung theo cách OO cổ điển rất nghiêm ngặt. Trong câu trả lời, imo mẫu NullObject bị lạm dụng một chút, vì nó đặc biệt nhằm tránh if (something is null)kiểm tra, vì NullObject có nghĩa là bao gồm tất cả các hành vi của một giá trị không tồn tại và bất kỳ cộng tác viên bên ngoài nào cũng không cần phải quan tâm đến việc đối tượng không tồn tại (null) hay không.
mất
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.