ตรวจสอบว่าค่า isset และ null


90

ฉันต้องการตรวจสอบว่าค่าถูกกำหนดให้เป็นอะไรหรือไม่รวมถึง null ด้วย ถือว่าเป็นโมฆะเป็นค่าที่ไม่ได้กำหนดและผลตอบแทนisset falseใช้ตัวอย่างต่อไปนี้:

$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

โปรดทราบว่าไม่ได้$barกำหนด

ฉันต้องหาเงื่อนไขที่ตรงตามสิ่งต่อไปนี้:

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

ความคิดใด ๆ ?


20
if (isset ($ foo)) // ส่งคืนเท็จฉันตกเก้าอี้ตลอดหลายปีที่ผ่านมา ...
max4ever

in_array ($ key, array_keys ($ _ SESSION)) && is_null ($ _ SESSION [$ key]) สงสัยมานานแล้ว ..
แจ็ค

1
นี่ไม่ใช่พฤติกรรมปกติสำหรับฉันisset= is set? ตัวแปรของคุณถูกตั้งค่าเป็น null ฉันเสียเวลาไปมากเพราะเรื่องนี้ ...
Vincent Decaux

คำตอบ:


85

IIRC คุณสามารถใช้get_defined_vars()สำหรับสิ่งนี้:

$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 ฉันจะแนะนำฟังก์ชั่นเดียวกันget_defined_varsรับมือกับขอบเขตอย่างมีความสุข
อาบน้ำ

1
ดูเหมือนจะใช้งานได้ แต่ฉันหวังว่าจะได้อะไรที่ง่ายกว่านี้ โอ้ดี. มาดูกันว่าจะมีใครมาซับเดียวได้บ้าง
Tatu Ulmanen

4
คุณไม่จำเป็นต้องมี vars ดังนั้นในทางทฤษฎีมันมีบรรทัดเดียว "if (array_key_exists ('foo', get_defined_vars ())) {}"
Hannes

fvn คำตอบของใหม่อาจจะเป็นวิธีที่รวดเร็วที่จะได้รับตัวแปรที่มีอยู่ในบริบทปัจจุบันหลีกเลี่ยงค่าใช้จ่ายของ:get_defined_vars() หรือเร็วกว่าถ้าทดสอบทั่วโลก:array_key_exists('foo', compact('foo')) array_key_exists('foo', $GLOBALS)
ToolmakerSteve

25

หากคุณกำลังจัดการกับคุณสมบัติของวัตถุที่อาจมีค่าเป็น NULL คุณสามารถใช้: property_exists()แทน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();

?>

ซึ่งตรงข้ามกับ isset () property_exists () จะคืนค่า TRUE แม้ว่าคุณสมบัติจะมีค่า NULL ก็ตาม


11
คุณสามารถทำเช่นเดียวกันกับอาร์เรย์ที่มี array_key_exists ();
teaqu

14

ดูวิธีที่ดีที่สุดในการทดสอบการมีอยู่ของตัวแปรใน PHP isset () เสียอย่างชัดเจน

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

3
รหัสที่คุณอ้างจะใช้ได้เฉพาะเมื่อตัวแปรอยู่ในขอบเขตส่วนกลาง
Raveline

แน่นอน แต่ไม่ใช่กรณีที่เกิดขึ้นบ่อยที่สุด? ในฟังก์ชันคุณจะมีตัวแปรที่ขอบเขตส่วนกลางและอาร์กิวเมนต์ (ซึ่งกำหนดไว้เสมอ) คุณยังสามารถมีคุณสมบัติของวัตถุ แต่คุณสามารถใช้ 'property_exists' ได้
LoïcFévrier

การใช้ $ GLOBALS ดูเหมือนจะผันผวนเล็กน้อยฉันต้องทำการทดสอบด้วยตัวเองก่อนจึงจะสามารถประกาศได้ว่าใช้งานได้
Tatu Ulmanen

4

ฉันพบว่าcompactเป็นฟังก์ชันที่ละเว้นตัวแปรที่ไม่ได้ตั้งค่า แต่ทำงานกับตัวแปรที่ตั้งค่าเป็นnullดังนั้นเมื่อคุณมีตารางสัญลักษณ์ท้องถิ่นขนาดใหญ่ฉันจะจินตนาการว่าคุณจะได้รับโซลูชันที่มีประสิทธิภาพมากกว่าการตรวจสอบ array_key_exists('foo', get_defined_vars())โดยใช้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

อัปเดต

เนื่องจาก PHP 7.3 compact ()จะแจ้งให้ทราบถึงค่าที่ไม่ได้ตั้งค่าดังนั้นทางเลือกนี้จึงใช้ไม่ได้อีกต่อไป

ตอนนี้ compact () ออกข้อผิดพลาดระดับ E_NOTICE หากสตริงที่ระบุอ้างถึงตัวแปรที่ไม่ได้ตั้งค่า ก่อนหน้านี้สตริงดังกล่าวถูกข้ามไปอย่างเงียบ ๆ


ทางเลือกที่น่าสนใจ แต่ทราบว่ามันอาจจะช้ากว่าการเรียก array_key_exists บนอาร์เรย์ที่มีอยู่เช่น $ GLOBALS - เพราะรูปลักษณ์ที่ขึ้นมาในตารางแฮชไม่ได้รับการใด ๆ compactที่ช้าลงเมื่อตารางที่ได้รับขนาดใหญ่และคุณได้เพิ่มการทำงานพิเศษของ อย่างไรก็ตามฉันโหวตให้คะแนนเพราะมีประโยชน์ในสถานการณ์หนึ่ง: หากคุณต้องการทราบว่าfooมีอยู่ในบริบทปัจจุบันหรือไม่ไม่ว่าจะมาจากที่ใดหากคุณไม่สนใจว่าจะเป็นระดับท้องถิ่นหรือระดับโลกเพียงแค่ต้องการทราบว่า มีอยู่
ToolmakerSteve

@ToolmakerSteve - get_defined_varsฉันเป็นจริงหมายถึงค่าใช้จ่ายอย่างมีนัยสำคัญที่อาจเกิดขึ้นในการโทร ดูที่นี่ .
nzn

1

โค้ดต่อไปนี้เขียนเป็นนามสกุล PHP เทียบเท่ากับ array_key_exists ($ name, get_defined_vars ()) (ขอบคุณ Henrik และ 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

คุณสามารถใช้is_nullและว่างแทน isset () Empty จะไม่พิมพ์ข้อความแสดงข้อผิดพลาดหากไม่มีตัวแปร


ฉันใช้ is_null ผลลัพธ์จะเหมือนกันโดยไม่คำนึงถึงisset.
Tatu Ulmanen

ฉันทำผิดพลาดขณะโพสต์คำตอบแรกของฉัน: คุณลองว่าง () หรือไม่?
Raveline

1
สิ่งนี้จะใช้ไม่ได้กับค่าที่ไม่ว่างเปล่าและไม่ใช่ค่า NULL เช่น FALSE, 0, array () หรือ ""
teaqu

1
คำตอบนี้ผิด is_nullมีปัญหาเดียวกันกับis_set: ไม่สามารถแยกความแตกต่างระหว่าง "not set" และ "set to null" ซึ่งเป็นปัญหาที่ OP มี emptyยิ่งแย่ไปกว่านั้นเมื่อ Calum ชี้ให้เห็น
ToolmakerSteve

0

ต่อไปนี้เป็นวิธีแก้ปัญหาโง่ ๆ โดยใช้ 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
ดูไม่น่าพก
สักเท่าไหร่

-3

is_null($bar)คืนค่าจริงเนื่องจากไม่มีค่าเลย หรือคุณสามารถใช้:

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

เพื่อตรวจสอบว่า$barมีการกำหนดไว้หรือไม่และจะคืนค่าจริงหาก:

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

ไม่มีเขาบอกว่าจะช่วยให้การเท็จเมื่อif(isset($bar)) $bar = null
LoïcFévrier

2
สิ่งนี้จะไม่ส่งผ่านตัวแปรอื่นใดนอกจาก null (เช่น if $bar = "test")
Tatu Ulmanen

3
เมื่อ $ bar = null isset () จะส่งคืน "false" และ is_null () จะคืนค่าจริง เท็จและจริงให้เท็จเสมอ
Bartek Kosa

คำตอบนี้ผิดอย่างสิ้นเชิง ในฐานะที่เป็น OP กล่าวว่ากลับเท็จแม้หลังจากที่isset($bar) $bar = null;
ToolmakerSteve
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.