Kiểm tra xem giá trị Isset và null


88

Tôi cần kiểm tra xem giá trị có được định nghĩa là bất kỳ thứ gì không, kể cả giá trị null. issetcoi các giá trị null là không xác định và trả về false. Lấy ví dụ sau:

$foo = null;

if(isset($foo)) // returns false
if(isset($bar)) // returns false
if(isset($foo) || is_null($foo)) // returns true
if(isset($bar) || is_null($bar)) // returns true, raises a notice

Lưu ý rằng $barkhông xác định.

Tôi cần tìm một điều kiện thỏa mãn những điều sau:

if(something($bar)) // returns false;
if(something($foo)) // returns true;

Có ý kiến ​​gì không?


19
if (isset ($ foo)) // returns sai sự thật, tôi bị rơi từ trên ghế, tất cả những năm ...
max4ever

in_array ($ key, array_keys ($ _ SESSION)) && is_null ($ _ SESSION [$ key]) Tôi đã tự hỏi điều này quá lâu ..
Jack

1
Đây không phải là một hành vi bình thường đối với tôi, isset= is set ?, biến của bạn được đặt ở null. Tôi lãng phí rất nhiều thời gian vì cái này ...
Vincent Decaux

Câu trả lời:


84

IIRC, bạn có thể sử dụng get_defined_vars()cho việc này:

$foo = NULL;
$vars = get_defined_vars();
if (array_key_exists('bar', $vars)) {}; // Should evaluate to FALSE
if (array_key_exists('foo', $vars)) {}; // Should evaluate to TRUE

+1 Tôi sẽ đề xuất chức năng tương tự, get_defined_varsvui vẻ đối phó với phạm vi.
chào đón

1
Có vẻ như đang làm việc, nhưng tôi đã hy vọng một cái gì đó đơn giản hơn. Ồ tốt. Hãy xem liệu có ai có thể nghĩ ra một lớp lót không.
Tatu Ulmanen

4
tốt, bạn không cần vars, vì vậy về lý thuyết, nó có một dòng "if (array_key_exists ('foo', get_defined_vars ())) {}"
Hannes

câu trả lời mới hơn FVN của có thể là một cách nhanh hơn để có được một biến tồn tại trong bối cảnh hiện nay, tránh các chi phí của get_defined_vars(): array_key_exists('foo', compact('foo')). Hoặc nhanh hơn, nếu thử nghiệm một toàn cầu: array_key_exists('foo', $GLOBALS).
ToolmakerSteve

25

Nếu bạn đang xử lý các thuộc tính đối tượng, whcih có thể có giá trị NULL, bạn có thể sử dụng: property_exists()thay vìisset()

<?php

class myClass {
    public $mine;
    private $xpto;
    static protected $test;

    function test() {
        var_dump(property_exists($this, 'xpto')); //true
    }
}

var_dump(property_exists('myClass', 'mine'));   //true
var_dump(property_exists(new myClass, 'mine')); //true
var_dump(property_exists('myClass', 'xpto'));   //true, as of PHP 5.3.0
var_dump(property_exists('myClass', 'bar'));    //false
var_dump(property_exists('myClass', 'test'));   //true, as of PHP 5.3.0
myClass::test();

?>

Ngược lại với Isset (), property_exists () trả về TRUE ngay cả khi thuộc tính có giá trị NULL.


11
Bạn có thể làm tương tự đối với các mảng với array_key_exists ();
teaqu

14

Xem Cách tốt nhất để kiểm tra sự tồn tại của một biến trong PHP; Isset () bị hỏng rõ ràng

 if( array_key_exists('foo', $GLOBALS) && is_null($foo)) // true & true => true
 if( array_key_exists('bar', $GLOBALS) && is_null($bar)) // false &  => false

3
Mã bạn trích dẫn chỉ hoạt động nếu biến nằm trong phạm vi toàn cục.
Raveline

Thật vậy, nhưng nó không phải là trường hợp thường xuyên nhất? Trong một hàm, bạn sẽ có các biến ở phạm vi toàn cục và các đối số (luôn được xác định). Bạn cũng có thể có thuộc tính đối tượng nhưng sau đó bạn có thể sử dụng 'property_exists'.
Loïc Février

Việc sử dụng $ GLOBALS có vẻ hơi dễ bay hơi, tôi phải tự mình thực hiện một số thử nghiệm trước khi có thể tuyên bố điều này là hoạt động.
Tatu Ulmanen

4

Tôi đã phát hiện ra rằng đó compactlà một hàm bỏ qua các biến chưa được đặt nhưng hoạt động trên những biến được đặt thành null, vì vậy khi bạn có một bảng ký hiệu cục bộ lớn, tôi sẽ tưởng tượng bạn có thể nhận được giải pháp hiệu quả hơn trong việc kiểm tra array_key_exists('foo', get_defined_vars())bằng cách sử dụng array_key_exists('foo', compact('foo')):

$foo = null;
echo isset($foo) ? 'true' : 'false'; // false
echo array_key_exists('foo', compact('foo')) ? 'true' : 'false'; // true
echo isset($bar) ? 'true' : 'false'; // false
echo array_key_exists('bar', compact('bar')) ? 'true' : 'false'; // false

Cập nhật

Kể từ phiên bản PHP 7.3, compact () sẽ đưa ra thông báo cho các giá trị chưa được đặt, vì vậy rất tiếc thay thế này không còn hợp lệ.

compact () hiện phát ra lỗi cấp E_NOTICE nếu một chuỗi nhất định tham chiếu đến một biến chưa được đặt. Trước đây, các chuỗi như vậy đã được bỏ qua một cách âm thầm.


Sự thay thế thú vị. Nhưng lưu ý rằng nó có thể chậm hơn so với việc gọi array_key_exists trên một mảng hiện có, chẳng hạn như $ GLOBALS - bởi vì việc tra cứu trong bảng băm không chậm hơn chút nào, khi bảng trở nên lớn và bạn đã thêm công việc bổ sung compact. Tuy nhiên, tôi đã ủng hộ nó vì nó hữu ích trong một tình huống: nếu bạn muốn biết liệu nó có footồn tại trong bối cảnh hiện tại hay không, bất kể nó đến từ đâu - nếu bạn không quan tâm là cục bộ hay toàn cầu, chỉ muốn biết nó tồn tại.
ToolmakerSteve

@ToolmakerSteve - Tôi thực sự đang đề cập đến chi phí gọi điện tiềm năng đáng kể get_defined_vars. Xem tại đây .
nzn

1

Đoạn mã sau được viết dưới dạng phần mở rộng PHP tương đương với array_key_exists ($ name, get_defined_vars ()) (nhờ Henrik và Hannes).

// get_defined_vars()
// https://github.com/php/php-src/blob/master/Zend/zend_builtin_functions.c#L1777
// array_key_exists
// https://github.com/php/php-src/blob/master/ext/standard/array.c#L4393

PHP_FUNCTION(is_defined_var)
{

    char *name;
    int name_len;

    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
        return;
    }

    if (!EG(active_symbol_table)) {
        zend_rebuild_symbol_table(TSRMLS_C);
    }

    if (zend_symtable_exists(EG(active_symbol_table), name, name_len + 1)) {
        RETURN_TRUE;
    }

}

0

Bạn có thể sử dụng is_nulltrống thay vì Isset (). Rỗng không in thông báo lỗi nếu biến không tồn tại.


Tôi đang sử dụng is_null. Kết quả là như nhau bất kể isset.
Tatu Ulmanen

Tôi đã mắc lỗi khi đăng câu trả lời đầu tiên của mình: bạn đã thử với trống () chưa?
Raveline

1
Điều này sẽ không hoạt động đối với các giá trị không trống và không phải NULL chẳng hạn như FALSE, 0, array () hoặc "".
teaqu

1
Câu trả lời này là sai. is_nullcó cùng một vấn đề như is_set: nó không thể phân biệt giữa "not set" và "set to null", đó là vấn đề OP gặp phải. emptythậm chí còn tệ hơn, như Calum chỉ ra.
ToolmakerSteve

0

Đây là một số cách giải quyết ngớ ngẩn bằng cách sử dụng xdebug. ;-)

function is_declared($name) {
    ob_start();
    xdebug_debug_zval($name);
    $content = ob_get_clean();

    return !empty($content);
}

$foo = null;
var_dump(is_declared('foo')); // -> true

$bla = 'bla';
var_dump(is_declared('bla')); // -> true

var_dump(is_declared('bar')); // -> false

1
Trông không di động cho lắm .. :)
Tatu Ulmanen 27/09/10

-3

is_null($bar)trả về true, vì nó không có giá trị nào cả. Ngoài ra, bạn có thể sử dụng:

if(isset($bar) && is_null($bar)) // returns false

để kiểm tra xem có $barđược xác định hay không và sẽ chỉ trả về true nếu:

$bar = null;
if(isset($bar) && is_null($bar)) // returns true

Không, anh ấy nói điều đó if(isset($bar))sai khi $bar = null.
Loïc Février

2
Điều này sẽ không chuyển bất kỳ biến nào khác ngoài null (ví dụ: nếu $bar = "test").
Tatu Ulmanen

3
Khi $ bar = null Isset () sẽ trả về "false" và is_null () sẽ trả về true. Sai và đúng luôn cho sai.
Bartek Kosa vào

Câu trả lời này hoàn toàn sai. Như OP đã nói, isset($bar)trả về false, thậm chí sau đó $bar = null;.
ToolmakerSteve
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.