#24274 [NEW]: New 'function' variable_exists(); patch included

From: Date: Fri, 20 Jun 2003 22:08:17 +0000
Subject: #24274 [NEW]: New 'function' variable_exists(); patch included
Groups: php.bugs 
Request: Send a blank email to php-bugs+get-42289@lists.php.net to get a copy of this message
From:             torben@php.net
Operating system: All
PHP version:      4CVS-2003-06-20 (stable)
PHP Bug Type:     Feature/Change Request
Bug description:  New 'function' variable_exists(); patch included

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 bug report at http://bugs.php.net/?id=24274&edit=1
-- 
Try a CVS snapshot:         http://bugs.php.net/fix.php?id=24274&r=trysnapshot
Fixed in CVS:               http://bugs.php.net/fix.php?id=24274&r=fixedcvs
Fixed in release:           http://bugs.php.net/fix.php?id=24274&r=alreadyfixed
Need backtrace:             http://bugs.php.net/fix.php?id=24274&r=needtrace
Try newer version:          http://bugs.php.net/fix.php?id=24274&r=oldversion
Not developer issue:        http://bugs.php.net/fix.php?id=24274&r=support
Expected behavior:          http://bugs.php.net/fix.php?id=24274&r=notwrong
Not enough info:            http://bugs.php.net/fix.php?id=24274&r=notenoughinfo
Submitted twice:            http://bugs.php.net/fix.php?id=24274&r=submittedtwice
register_globals:           http://bugs.php.net/fix.php?id=24274&r=globals
PHP 3 support discontinued: http://bugs.php.net/fix.php?id=24274&r=php3
Daylight Savings:           http://bugs.php.net/fix.php?id=24274&r=dst
IIS Stability:              http://bugs.php.net/fix.php?id=24274&r=isapi
Install GNU Sed:            http://bugs.php.net/fix.php?id=24274&r=gnused



Thread (7 messages)

« previous php.bugs (#42289) next »