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

From: Date: Fri, 20 Jun 2003 22:28:37 +0000
Subject: #24274 [Com]: New 'function' variable_exists(); patch included
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-42290@lists.php.net to get a copy of this message
 ID:               24274
 Comment by:       torben at thebuttlesschaps dot com
 Reported By:      torben@php.net
 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] torben@php.net

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



Thread (7 messages)

« previous php.bugs (#42290) next »