Cách tốt nhất để cung cấp cho biến một giá trị mặc định (mô phỏng Perl | |, || =)


134

Tôi thích làm điều này trong Perl: $foo = $bar || $bazgán $bazcho $foonếu $bartrống hoặc không xác định. Bạn cũng có $foo ||= $bletchmà sẽ chỉ gán $bletchtới $foonếu $fookhông được định nghĩa đúng hoặc bỏ trống.

Các nhà điều hành ternary trong tình huống này là tẻ nhạt và mệt mỏi. Chắc chắn có một phương thức đơn giản, thanh lịch có sẵn trong PHP?

Hoặc là câu trả lời duy nhất cho một hàm tùy chỉnh sử dụng isset ()?



1
BTW các nhà khai thác với các chức năng mong muốn Perl là ////=và họ tồn tại như của Perl v5.10.0. Bản gốc ||||=kiểm tra giá trị logic, không xác định.
Palec

@Palec, tại sao một câu hỏi 4 tuổi với 29 câu hỏi được xác định là một bản sao của câu hỏi 1 năm tuổi với 6 câu hỏi (nó được đánh dấu là một bản sao của câu hỏi khác?) Tôi nghĩ rằng có giá trị lớn trong việc giữ câu hỏi này câu hỏi, vì tiêu đề là chung chung hơn (không tham khảo câu trả lời, ví dụ: isset ()).
Tom Auger

Chúng trùng lặp rõ ràng và chính xác. Nó thừa nhận tôi đã không nghĩ nhiều về cái nào nên là bản gốc, tôi đang ở giữa một thứ khác, tạo ra mối liên kết giữa hai người là mục tiêu. Rút lại VTC của tôi.
Palec

Một bản sao chính xác, được đánh dấu (IMO một cách sai lầm) là một bản sao của một câu hỏi khác: tốc ký PHP cho isset ()?
Palec

Câu trả lời:


130

Trong PHP 7 cuối cùng chúng ta cũng có một cách để làm điều này một cách thanh lịch. Nó được gọi là toán tử liên kết Null . Bạn có thể sử dụng nó như thế này:

$name = $_GET['name'] ?? 'john doe';

Điều này tương đương với

$name = isset($_GET['name']) ? $_GET['name']:'john doe';

14
Tôi cho rằng người vận hành tàu vũ trụ cũng có công.
Mariano

3
Tôi nghĩ Mariano đang kéo chân chúng tôi nhưng không, đó là một điều <=>và khá chính xác để khởi động!
HPWD

1
Lưu ý rằng toán tử hợp nhất null hoạt động khác với toán tử có điều kiện, vì nó đặc trưng cho một nullgiá trị. Ví dụ: nếu $_GET['name']được đặt thành một chuỗi trống, dòng đầu tiên sẽ trả về một chuỗi trống, nhưng chúng ta có thể trả về "john doe" bằng cách sử dụng $_GET['name'] ? $_GET['name'] : 'john doe'.
VPh Phantom

211

PHP 5.3 có một ?:toán tử tốc ký :

$foo = $bar ?: $baz;

Việc gán này $barnếu nó không phải là một giá trị trống (tôi không biết điều này sẽ khác với PHP như thế nào so với Perl), nếu không $baz, và giống như trong phiên bản Perl và các phiên bản cũ hơn của PHP:

$foo = $bar ? $bar : $baz;

Nhưng PHP không có toán tử gán gán cho việc này (nghĩa là không tương đương với Perl's ||=).

Ngoài ra, PHP sẽ gây ồn nếu $barkhông được đặt trừ khi bạn tắt thông báo. Cũng có một sự khác biệt về ngữ nghĩa giữa isset()empty(). Cái trước trả về false nếu biến không tồn tại hoặc được đặt thành NULL. Lợi nhuận sau đúng nếu nó không tồn tại, hoặc được thiết lập để 0, '', falsehoặc NULL.


2
+1 Để giới thiệu cho tôi một tính năng tuyệt vời khác của 5.3 Tôi đang bỏ lỡ trong các máy chủ RHEL5 / PHP5.1.2 của mình.
Michael Berkowski

Tôi đoán bạn có nghĩa là The first returnsthay vì The secondtrong câu áp chót của bạn.
Toto

21
Lưu ý rằng nếu biến của bạn không được xác định, PHP sẽ đưa ra các thông báo về nó. Thật không may, điều này không thay thế cho $var = isset($var) ? $var : 'default value'; Nó nói rằng trong câu trả lời ... chỉ cần chỉ ra một lần nữa cho bất cứ ai lướt qua nó. :-D
Brad

6
Có tệ không khi làm $ var = @ $ var ?: 'Giá trị mặc định'; Nếu vậy, tại sao? Cho rằng "lỗi" duy nhất có thể là $ var không được đặt và chúng tôi không quan tâm nếu $ var không được đặt ...
Codemonkey

8

Cảm ơn về tất cả những câu trả lời tuyệt vời!

Đối với bất kỳ ai khác đến đây để thay thế có thể, đây là một số chức năng giúp đưa tedium ra khỏi loại điều này.

function set_if_defined(&$var, $test){
    if (isset($test)){
        $var = $test;
        return true;
    } else {
        return false;
    }
}

function set_unless_defined(&$var, $default_var){
    if (! isset($var)){
        $var = $default_var;
        return true;
    } else {
        return false;
    }
}

function select_defined(){
    $l = func_num_args();
    $a = func_get_args();
    for ($i=0; $i<$l; $i++){
        if ($a[$i]) return $a[$i];
    }
}

Ví dụ:

// $foo ||= $bar;
set_unless_defined($foo, $bar);

//$foo = $baz || $bletch
$foo = select_defined($baz, $bletch);

Tôi chắc chắn những điều này có thể được cải thiện.


7

Một thành ngữ phổ biến để duy trì khả năng tương thích với các phiên bản PHP cũ hơn là:

 $var = $bool   or   $var = "default";
 // If I use it, then only with excessive spaces for clarity.

Điều này làm việc cho các giá trị có thể được đánh giá trong bối cảnh boolean. Ưu điểm ở đây là nó cũng cung cấp cho bạn thông báo gỡ lỗi e_notice nếu biến không được xác định.


Là một thông báo không được phát ra $bool ? $bool : "default"nếu $boolkhông được xác định?
BoltClock

Chắc chắn, đó là như nhau. Tôi giả sử OP đang đề cập đến isset($var) ? $var : DEFAULT. Nhưng có vẻ như anh ấy muốn xa lánh họ.
mario

6

Trong PHP sớm hơn 7. *, người ta có thể sử dụng ?: Cho một biến không xác định có lỗi bị loại bỏ cục bộ với một @:

$foo = @$bar ?: $baz;

0

đây là một định dạng tốt cho issettrường hợp

isset($foo) || $foo= $bar;

một cách đơn giản khác và sẽ cung cấp cho bạn nhiều quyền kiểm soát hơn khi bạn có thể thêm nhiều điều kiện hơn và gán cho một biến khác cùng một lúc

$foo = (isset($oData['foo']))?$bar['foo']:'default value';


0

Một giải pháp khả thi: defaultFor ()

Trừ khi chúng tôi có một giải pháp nhà máy (điều này thực sự rất khó chịu), tôi muốn giới thiệu người trợ giúp nhỏ sau đây. Nó thực hiện công việc trong hầu hết các trường hợp:


    function defaultFor(&$x,$default=null) {
        if(!isset($x)) $x = $default;
    }

    //--------------------  Now you can do this: --------------

    defaultFor($a,"Jack");  // if $a is not set, it will be "Jack"
    defaultFor($x);         // no more notices for $x but keep it !isset

Tôi hy vọng điều này gần với những gì bạn muốn đạt được. Nó sẽ không cung cấp cho bạn bất kỳ thông báo nào nếu bạn sử dụng nó với một biến không tồn tại và nó khá thuận tiện. Chắc chắn nó có một nhược điểm: giá trị mặc định luôn được tính toán trước vì vậy đừng sử dụng nó với bất kỳ thứ gì nặng như tham số thứ hai, như file_get_contents hoặc thứ gì đó. Trong những trường hợp đó, bạn tốt hơn với ngay lập tức.

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.