ID: 24274 Comment by: torben at thebuttlesschaps dot com Reported By: [EMAIL PROTECTED] Status: Open Bug Type: Feature/Change Request Operating System: All PHP Version: 4CVS-2003-06-20 (stable) New Comment:
Hmm. A non-messed-up patch can be found here: http://www.thebuttlesschaps.com/variable_exists_patch.txt Torben Previous Comments: ------------------------------------------------------------------------ [2003-06-20 17:08:17] [EMAIL PROTECTED] Description: ------------ PHP doesn't have a way to check whether a variable exists; just a way to check whether it has a value (isset()). This isn't wrong, but it would be useful to add a way to check for actual existence of a variable (for instance, checking for array keys without having to go through array_key_exists()). Here's a patch against CVS which implements variable_exists(). The only difference to isset() is that a variable is considered to exist even if it contains NULL. Index: zend_compile.h =================================================================== RCS file: /repository/Zend/zend_compile.h,v retrieving revision 1.145 diff -u -r1.145 zend_compile.h --- zend_compile.h 31 Dec 2002 15:55:02 -0000 1.145 +++ zend_compile.h 20 Jun 2003 11:35:20 -0000 @@ -558,6 +558,7 @@ #define ZEND_ISSET (1<<0) #define ZEND_ISEMPTY (1<<1) +#define ZEND_VARIABLE_EXISTS (1<<2) #define ZEND_CT (1<<0) #define ZEND_RT (1<<1) Index: zend_execute.c =================================================================== RCS file: /repository/Zend/zend_execute.c,v retrieving revision 1.321 diff -u -r1.321 zend_execute.c --- zend_execute.c 31 Dec 2002 15:55:02 -0000 1.321 +++ zend_execute.c 20 Jun 2003 11:35:22 -0000 @@ -2382,7 +2382,7 @@ isset = 1; } } - } else if (*var==EG(uninitialized_zval_ptr) || ((*var)->type == IS_NULL)) { + } else if (*var == EG(uninitialized_zval_ptr) || (((*var)->type == IS_NULL) && EX(opline)->op2.u.constant.value.lval != ZEND_VARIABLE_EXISTS)) { value = *var; isset = 0; } else { @@ -2391,6 +2391,7 @@ } switch (EX(opline)->op2.u.constant.value.lval) { + case ZEND_VARIABLE_EXISTS: case ZEND_ISSET: EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = isset; break; Index: zend_language_parser.y =================================================================== RCS file: /repository/Zend/zend_language_parser.y,v retrieving revision 1.23 diff -u -r1.23 zend_language_parser.y --- zend_language_parser.y 4 Aug 2002 06:39:44 -0000 1.23 +++ zend_language_parser.y 20 Jun 2003 11:35:22 -0000 @@ -112,6 +112,7 @@ %token T_UNSET %token T_ISSET %token T_EMPTY +%token T_VARIABLE_EXISTS %token T_CLASS %token T_EXTENDS %token T_OBJECT_OPERATOR @@ -710,6 +711,7 @@ internal_functions_in_yacc: T_ISSET '(' isset_variables ')' { $$ = $3; } + | T_VARIABLE_EXISTS '(' variable_exists_variables ')' { $$ = $3; } | T_EMPTY '(' cvar ')' { zend_do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 TSRMLS_CC); } | T_INCLUDE expr { zend_do_include_or_eval(ZEND_INCLUDE, &$$, &$2 TSRMLS_CC); } | T_INCLUDE_ONCE expr { zend_do_include_or_eval(ZEND_INCLUDE_ONCE, &$$, &$2 TSRMLS_CC); } @@ -717,6 +719,11 @@ | T_REQUIRE expr { zend_do_include_or_eval(ZEND_REQUIRE, &$$, &$2 TSRMLS_CC); } | T_REQUIRE_ONCE expr { zend_do_include_or_eval(ZEND_REQUIRE_ONCE, &$$, &$2 TSRMLS_CC); } ; + +variable_exists_variables: + cvar { zend_do_isset_or_isempty(ZEND_VARIABLE_EXISTS, &$$, &$1 TSRMLS_CC); } + | variable_exists_variables ',' { zend_do_boolean_and_begin(&$1, &$2 TSRMLS_CC); } cvar { znode tmp; zend_do_isset_or_isempty(ZEND_ISSET, &tmp, &$4 TSRMLS_CC); zend_do_boolean_and_end(&$$, &$1, &tmp, &$2 TSRMLS_CC); } +; isset_variables: cvar { zend_do_isset_or_isempty(ZEND_ISSET, &$$, &$1 TSRMLS_CC); } Index: zend_language_scanner.l =================================================================== RCS file: /repository/Zend/zend_language_scanner.l,v retrieving revision 1.64 diff -u -r1.64 zend_language_scanner.l --- zend_language_scanner.l 13 Feb 2003 16:46:16 -0000 1.64 +++ zend_language_scanner.l 20 Jun 2003 11:35:23 -0000 @@ -927,6 +927,10 @@ return T_ISSET; } +<ST_IN_SCRIPTING>"variable_exists" { + return T_VARIABLE_EXISTS; +} + <ST_IN_SCRIPTING>"empty" { return T_EMPTY; } Reproduce code: --------------- <?php error_reporting(E_ALL); ini_set('display_errors', true); echo "<h3>Array testing</h3>"; echo "\$arr = array(1 => null, 2 => array(1 => 3, 2 => null));\n\n"; $arr = array(1 => null, 2 => array(1 => 3, 2 => null)); echo "variable_exists(\$arr[1]): " . (variable_exists($arr[1]) ? 'yes' : 'no') . " (should be yes)\n"; echo "variable_exists(\$arr[2]): " . (variable_exists($arr[2]) ? 'yes' : 'no') . " (should be yes)\n"; echo "variable_exists(\$arr[3]): " . (variable_exists($arr[3]) ? 'yes' : 'no') . " (should be no)\n"; echo "variable_exists(\$arr[1][2]): " . (variable_exists($arr[1][2]) ? 'yes' : 'no') . " (should be no)\n"; echo "variable_exists(\$arr[2][1]): " . (variable_exists($arr[2][1]) ? 'yes' : 'no') . " (should be yes)\n"; echo "variable_exists(\$arr[2][2]): " . (variable_exists($arr[2][2]) ? 'yes' : 'no') . " (should be yes)\n"; echo "variable_exists(\$arr[2][3]): " . (variable_exists($arr[2][3]) ? 'yes' : 'no') . " (should be no)\n"; echo "<h3>Scalar testing</h3>"; echo "\$foo = null\n\n"; $foo = null; echo "variable_exists(\$foo): " . (variable_exists($foo) ? 'yes' : 'no') . " (should be yes)\n"; echo "unset(\$foo);\n"; unset($foo); echo "variable_exists(\$foo): " . (variable_exists($foo) ? 'yes' : 'no') . " (should be no)\n"; echo "variable_exists(\$bar): " . (variable_exists($bar) ? 'yes' : 'no') . " (should be no)\n"; ?> Actual result: -------------- (Actual output from PHP 4.3.2 with the given patch): Array testing $arr = array(1 => null, 2 => array(1 => 3, 2 => null)); variable_exists($arr[1]): yes (should be yes) variable_exists($arr[2]): yes (should be yes) variable_exists($arr[3]): no (should be no) variable_exists($arr[1][2]): no (should be no) variable_exists($arr[2][1]): yes (should be yes) variable_exists($arr[2][2]): yes (should be yes) variable_exists($arr[2][3]): no (should be no) Scalar testing $foo = null variable_exists($foo): yes (should be yes) unset($foo); variable_exists($foo): no (should be no) variable_exists($bar): no (should be no) ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=24274&edit=1