method, using Closure::fromCallable() or ReflectionMethod::getClosure().
. Also removed ability to unbind $this from proper closures that contain uses
of $this.
+ . Removed ability to use array_key_exists() with objects. Use one of isset()
+ or property_exists() instead.
. Any array that has a number n as its first numeric key will use n+1 for
its next implicit key. Even if n is negative.
RFC: https://wiki.php.net/rfc/negative_array_index
}
}
-static zend_never_inline uint32_t ZEND_FASTCALL zend_array_key_exists_fast(HashTable *ht, zval *key OPLINE_DC EXECUTE_DATA_DC)
+static zend_never_inline zend_bool ZEND_FASTCALL zend_array_key_exists_fast(HashTable *ht, zval *key OPLINE_DC EXECUTE_DATA_DC)
{
zend_string *str;
zend_ulong hval;
goto num_key;
}
str_key:
- return zend_hash_find_ind(ht, str) != NULL ? IS_TRUE : IS_FALSE;
+ return zend_hash_find_ind(ht, str) != NULL;
} else if (EXPECTED(Z_TYPE_P(key) == IS_LONG)) {
hval = Z_LVAL_P(key);
num_key:
- return zend_hash_index_find(ht, hval) != NULL ? IS_TRUE : IS_FALSE;
+ return zend_hash_index_find(ht, hval) != NULL;
} else if (EXPECTED(Z_ISREF_P(key))) {
key = Z_REFVAL_P(key);
goto try_again;
goto str_key;
} else {
zend_error(E_WARNING, "array_key_exists(): The first argument should be either a string or an integer");
- return IS_FALSE;
+ return 0;
}
}
-static zend_never_inline uint32_t ZEND_FASTCALL zend_array_key_exists_slow(zval *subject, zval *key OPLINE_DC EXECUTE_DATA_DC)
+static ZEND_COLD void ZEND_FASTCALL zend_array_key_exists_error(
+ zval *subject, zval *key OPLINE_DC EXECUTE_DATA_DC)
{
- if (EXPECTED(Z_TYPE_P(subject) == IS_OBJECT)) {
- zend_error(E_DEPRECATED, "array_key_exists(): "
- "Using array_key_exists() on objects is deprecated. "
- "Use isset() or property_exists() instead");
-
- HashTable *ht = zend_get_properties_for(subject, ZEND_PROP_PURPOSE_ARRAY_CAST);
- uint32_t result = zend_array_key_exists_fast(ht, key OPLINE_CC EXECUTE_DATA_CC);
- zend_release_properties(ht);
- return result;
- } else {
- if (UNEXPECTED(Z_TYPE_P(key) == IS_UNDEF)) {
- ZVAL_UNDEFINED_OP1();
- }
- if (UNEXPECTED(Z_TYPE_INFO_P(subject) == IS_UNDEF)) {
- ZVAL_UNDEFINED_OP2();
- }
- zend_type_error("array_key_exists() expects parameter 2 to be array, %s given", zend_get_type_by_const(Z_TYPE_P(subject)));
- return IS_NULL;
+ if (Z_TYPE_P(key) == IS_UNDEF) {
+ ZVAL_UNDEFINED_OP1();
+ }
+ if (Z_TYPE_P(subject) == IS_UNDEF) {
+ ZVAL_UNDEFINED_OP2();
+ }
+ if (!EG(exception)) {
+ zend_type_error("array_key_exists() expects parameter 2 to be array, %s given",
+ zend_get_type_by_const(Z_TYPE_P(subject)));
}
}
case ZEND_PROP_PURPOSE_SERIALIZE:
case ZEND_PROP_PURPOSE_VAR_EXPORT:
case ZEND_PROP_PURPOSE_JSON:
- case _ZEND_PROP_PURPOSE_ARRAY_KEY_EXISTS:
ht = obj->handlers->get_properties(obj);
if (ht && !(GC_FLAGS(ht) & GC_IMMUTABLE)) {
GC_ADDREF(ht);
ZEND_PROP_PURPOSE_VAR_EXPORT,
/* Used for json_encode(). */
ZEND_PROP_PURPOSE_JSON,
- /* array_key_exists(). Not intended for general use! */
- _ZEND_PROP_PURPOSE_ARRAY_KEY_EXISTS,
/* Dummy member to ensure that "default" is specified. */
_ZEND_PROP_PURPOSE_NON_EXHAUSTIVE_ENUM
} zend_prop_purpose;
zval *key, *subject;
HashTable *ht;
- uint32_t result;
+ zend_bool result;
SAVE_OPLINE();
ZEND_VM_C_GOTO(array_key_exists_array);
}
}
- result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ result = 0;
}
FREE_OP2();
FREE_OP1();
- ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
+ ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
zval *key, *subject;
HashTable *ht;
- uint32_t result;
+ zend_bool result;
SAVE_OPLINE();
goto array_key_exists_array;
}
}
- result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ result = 0;
}
- ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
+ ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
zval *key, *subject;
HashTable *ht;
- uint32_t result;
+ zend_bool result;
SAVE_OPLINE();
goto array_key_exists_array;
}
}
- result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ result = 0;
}
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
- ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
+ ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
zval *key, *subject;
HashTable *ht;
- uint32_t result;
+ zend_bool result;
SAVE_OPLINE();
goto array_key_exists_array;
}
}
- result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ result = 0;
}
- ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
+ ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
zval *key, *subject;
HashTable *ht;
- uint32_t result;
+ zend_bool result;
SAVE_OPLINE();
goto array_key_exists_array;
}
}
- result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ result = 0;
}
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
- ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
+ ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
zval *key, *subject;
HashTable *ht;
- uint32_t result;
+ zend_bool result;
SAVE_OPLINE();
goto array_key_exists_array;
}
}
- result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ result = 0;
}
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
- ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
+ ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
zval *key, *subject;
HashTable *ht;
- uint32_t result;
+ zend_bool result;
SAVE_OPLINE();
goto array_key_exists_array;
}
}
- result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ result = 0;
}
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
- ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
+ ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
zval *key, *subject;
HashTable *ht;
- uint32_t result;
+ zend_bool result;
SAVE_OPLINE();
goto array_key_exists_array;
}
}
- result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ result = 0;
}
- ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
+ ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
zval *key, *subject;
HashTable *ht;
- uint32_t result;
+ zend_bool result;
SAVE_OPLINE();
goto array_key_exists_array;
}
}
- result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ result = 0;
}
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
- ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
+ ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
zval *key, *subject;
HashTable *ht;
- uint32_t result;
+ zend_bool result;
SAVE_OPLINE();
goto array_key_exists_array;
}
}
- result = zend_array_key_exists_slow(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ zend_array_key_exists_error(subject, key OPLINE_CC EXECUTE_DATA_CC);
+ result = 0;
}
- ZEND_VM_SMART_BRANCH(result == IS_TRUE, 1);
+ ZEND_VM_SMART_BRANCH(result, 1);
}
/* No specialization for op_types (CONST|TMPVAR|UNUSED|CV, ANY) */
break;
case ZEND_PROP_PURPOSE_VAR_EXPORT:
case ZEND_PROP_PURPOSE_JSON:
- case _ZEND_PROP_PURPOSE_ARRAY_KEY_EXISTS:
dup = 0;
break;
default:
var_dump(empty($b['b'])); //true
var_dump(empty($b[37])); //true
-var_dump(array_key_exists('b', $b)); //true
var_dump($b['b']);
$a = array('b' => '', 37 => false);
bool(false)
bool(true)
bool(true)
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(true)
NULL
bool(true)
bool(true)
PHP_FUNCTION(array_key_exists)
{
zval *key;
- zval *array;
HashTable *ht;
ZEND_PARSE_PARAMETERS_START(2, 2)
Z_PARAM_ZVAL(key)
- Z_PARAM_ARRAY_OR_OBJECT(array)
+ Z_PARAM_ARRAY_HT(ht)
ZEND_PARSE_PARAMETERS_END();
- if (EXPECTED(Z_TYPE_P(array) == IS_ARRAY)) {
- ht = Z_ARRVAL_P(array);
- } else {
- ht = zend_get_properties_for(array, ZEND_PROP_PURPOSE_ARRAY_CAST);
- php_error_docref(NULL, E_DEPRECATED,
- "Using array_key_exists() on objects is deprecated. "
- "Use isset() or property_exists() instead");
- }
-
switch (Z_TYPE_P(key)) {
case IS_STRING:
RETVAL_BOOL(zend_symtable_exists_ind(ht, Z_STR_P(key)));
php_error_docref(NULL, E_WARNING, "The first argument should be either a string or an integer");
RETVAL_FALSE;
}
-
- if (Z_TYPE_P(array) != IS_ARRAY) {
- zend_release_properties(ht);
- }
}
/* }}} */
echo "\n*** Testing operation on objects ***\n";
class key_check
{
- private $private_var = "Priviate var";
- protected $protected_var = "Protected var";
- public $public_var = "Public var";
- public $arr = array("var" => "value", "1" => "one", ""=>"value");
- public function print_member()
- {
- echo $this->$private_var."\n";
- echo $this->$protected_var."\n";
- echo $this->$public_var."\n";
- }
+ public $public_var = "Public var";
}
$key_check_obj = new key_check; //new object
-/* array_key_exists() on an object, it should work on only public member variables */
-var_dump(array_key_exists("private_var", $key_check_obj)); // not found, private member
-var_dump(array_key_exists("protected_var", $key_check_obj)); // not found, private member
-var_dump(array_key_exists("public_var", $key_check_obj)); // found, public member
-var_dump(array_key_exists("print_member", $key_check_obj)); // not found, its a function
-var_dump(array_key_exists("arr", $key_check_obj)); //found, public member
-var_dump(array_key_exists("var", $key_check_obj->arr)); //found, key is in member array
+try {
+ var_dump(array_key_exists("public_var", $key_check_obj));
+} catch (TypeError $e) {
+ echo $e->getMessage(), "\n";
+}
-/* error condition, first argument as object */
-var_dump( array_key_exists($key_check_obj, $key_check_obj) );
echo "Done\n";
?>
--EXPECTF--
bool(false)
*** Testing operation on objects ***
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(false)
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(false)
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(true)
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(false)
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(true)
-bool(true)
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-
-Warning: array_key_exists(): The first argument should be either a string or an integer in %s on line %d
-bool(false)
+array_key_exists() expects parameter 2 to be array, object given
Done
+++ /dev/null
---TEST--
-Test array_key_exists() function : object functionality
---FILE--
-<?php
-/* Prototype : bool array_key_exists(mixed $key, array $search)
- * Description: Checks if the given key or index exists in the array
- * Source code: ext/standard/array.c
- * Alias to functions: key_exists
- */
-
-/*
- * Test basic functionality of array_key_exists() with objects
- */
-
-echo "*** Testing array_key_exists() : object functionality ***\n";
-
-class myClass {
- var $var1;
- var $var2;
- var $var3;
-
- function __construct($a, $b, $c = null) {
- $this->var1 = $a;
- $this->var2 = $b;
- if (!is_null($c)) {
- $this->var3 = $c;
- }
- }
-}
-
-echo "\n-- Do not assign a value to \$class1->var3 --\n";
-$class1 = new myClass ('a', 'b');
-echo "\$key = var1:\n";
-var_dump(array_key_exists('var1', $class1));
-echo "\$key = var3:\n";
-var_dump(array_key_exists('var3', $class1));
-echo "\$class1:\n";
-var_dump($class1);
-
-echo "\n-- Assign a value to \$class2->var3 --\n";
-$class2 = new myClass('x', 'y', 'z');
-echo "\$key = var3:\n";
-var_dump(array_key_exists('var3', $class2));
-echo "\$class2:\n";
-var_dump($class2);
-
-echo "Done";
-?>
---EXPECTF--
-*** Testing array_key_exists() : object functionality ***
-
--- Do not assign a value to $class1->var3 --
-$key = var1:
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(true)
-$key = var3:
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(true)
-$class1:
-object(myClass)#1 (3) {
- ["var1"]=>
- string(1) "a"
- ["var2"]=>
- string(1) "b"
- ["var3"]=>
- NULL
-}
-
--- Assign a value to $class2->var3 --
-$key = var3:
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(true)
-$class2:
-object(myClass)#2 (3) {
- ["var1"]=>
- string(1) "x"
- ["var2"]=>
- string(1) "y"
- ["var3"]=>
- string(1) "z"
-}
-Done
+++ /dev/null
---TEST--
-Test array_key_exists() function : object functionality - different visibilities
---FILE--
-<?php
-/* Prototype : bool array_key_exists(mixed $key, array $search)
- * Description: Checks if the given key or index exists in the array
- * Source code: ext/standard/array.c
- * Alias to functions: key_exists
- */
-
-/*
- * Pass array_key_exists() an object with private and protected properties
- */
-
-echo "*** Testing array_key_exists() : object functionality ***\n";
-
-class myClass {
- public $var1;
- protected $var2;
- private $var3;
-
- function __construct($a, $b, $c = null) {
- $this->var1 = $a;
- $this->var2 = $b;
- if (!is_null($c)) {
- $this->var3 = $c;
- }
- }
-}
-
-echo "\n-- Do not assign a value to \$class1->var3 --\n";
-$class1 = new myClass ('a', 'b');
-echo "\$key = var1:\n";
-var_dump(array_key_exists('var1', $class1));
-echo "\$key = var2:\n";
-var_dump(array_key_exists('var2', $class1));
-echo "\$key = var3:\n";
-var_dump(array_key_exists('var3', $class1));
-echo "\$class1:\n";
-var_dump($class1);
-
-echo "\n-- Assign a value to \$class2->var3 --\n";
-$class2 = new myClass('x', 'y', 'z');
-echo "\$key = var3:\n";
-var_dump(array_key_exists('var3', $class2));
-echo "\$class2:\n";
-var_dump($class2);
-
-echo "Done";
-?>
---EXPECTF--
-*** Testing array_key_exists() : object functionality ***
-
--- Do not assign a value to $class1->var3 --
-$key = var1:
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(true)
-$key = var2:
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(false)
-$key = var3:
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(false)
-$class1:
-object(myClass)#1 (3) {
- ["var1"]=>
- string(1) "a"
- ["var2":protected]=>
- string(1) "b"
- ["var3":"myClass":private]=>
- NULL
-}
-
--- Assign a value to $class2->var3 --
-$key = var3:
-
-Deprecated: array_key_exists(): Using array_key_exists() on objects is deprecated. Use isset() or property_exists() instead in %s on line %d
-bool(false)
-$class2:
-object(myClass)#2 (3) {
- ["var1"]=>
- string(1) "x"
- ["var2":protected]=>
- string(1) "y"
- ["var3":"myClass":private]=>
- string(1) "z"
-}
-Done