Commit 045d005f809 for php.net

commit 045d005f80934d4a122145d1afef767f7b5039e5
Author: Gina Peter Banyard <girgias@php.net>
Date:   Tue Aug 25 22:51:37 2026 +0100

    mysqli: move behaviour existing only for mysqli_fetch_object() into it (#23451)

    The shared function is effectively ignored for mysqli_fetch_object() so just move the relevant behaviour and simplify the common implementation

diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index 2f1fa1c21c5..e6f87643357 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -747,72 +747,30 @@ void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * result, zend

 /* TODO Split this up */
 /* {{{ php_mysqli_fetch_into_hash */
-void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags, int into_object)
+void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags)
 {
 	MYSQL_RES		*result;
 	zval			*mysql_result;
 	zend_long			fetchtype;
-	HashTable			*ctor_params = NULL;
-	zend_class_entry *ce = NULL;

-	if (into_object) {
-		if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|Ch", &mysql_result, mysqli_result_class_entry, &ce, &ctor_params) == FAILURE) {
+	if (override_flags) {
+		ZEND_ASSERT(override_flags >= MYSQLI_ASSOC && override_flags <= MYSQLI_BOTH);
+		if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
 			RETURN_THROWS();
 		}
-		if (ce == NULL) {
-			ce = zend_standard_class_def;
-		}
-		if (UNEXPECTED(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
-			zend_throw_error(NULL, "Class %s cannot be instantiated", ZSTR_VAL(ce->name));
+		fetchtype = override_flags;
+	} else {
+		fetchtype = MYSQLI_BOTH;
+		if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &fetchtype) == FAILURE) {
 			RETURN_THROWS();
 		}
-		fetchtype = MYSQLI_ASSOC;
-	} else {
-		if (override_flags) {
-			if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
-				RETURN_THROWS();
-			}
-			fetchtype = override_flags;
-		} else {
-			fetchtype = MYSQLI_BOTH;
-			if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|l", &mysql_result, mysqli_result_class_entry, &fetchtype) == FAILURE) {
-				RETURN_THROWS();
-			}
+		if (fetchtype < MYSQLI_ASSOC || fetchtype > MYSQLI_BOTH) {
+			zend_argument_value_error(ERROR_ARG_POS(2), "must be one of MYSQLI_NUM, MYSQLI_ASSOC, or MYSQLI_BOTH");
+			RETURN_THROWS();
 		}
 	}
 	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID);

-	if (fetchtype < MYSQLI_ASSOC || fetchtype > MYSQLI_BOTH) {
-		zend_argument_value_error(ERROR_ARG_POS(2), "must be one of MYSQLI_NUM, MYSQLI_ASSOC, or MYSQLI_BOTH");
-		RETURN_THROWS();
-	}
-
 	php_mysqli_fetch_into_hash_aux(return_value, result, fetchtype);
-
-	if (into_object && Z_TYPE_P(return_value) == IS_ARRAY) {
-		zval dataset;
-
-		ZVAL_COPY_VALUE(&dataset, return_value);
-
-		object_init_ex(return_value, ce);
-		HashTable *prop_table = zend_symtable_to_proptable(Z_ARR(dataset));
-		zval_ptr_dtor(&dataset);
-		if (!ce->default_properties_count && !ce->__set) {
-			Z_OBJ_P(return_value)->properties = prop_table;
-		} else {
-			zend_merge_properties(return_value, prop_table);
-			zend_array_release(prop_table);
-		}
-
-		if (ce->constructor) {
-			zend_call_known_function(ce->constructor, Z_OBJ_P(return_value), Z_OBJCE_P(return_value),
-				/* retval */ NULL, /* argc */ 0, /* params */ NULL, ctor_params);
-		} else if (ctor_params && zend_hash_num_elements(ctor_params) > 0) {
-			zend_argument_value_error(ERROR_ARG_POS(3),
-				"must be empty when the specified class (%s) does not have a constructor",
-				ZSTR_VAL(ce->name)
-			);
-		}
-	}
 }
 /* }}} */
diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c
index 526fd10b262..e55083d940c 100644
--- a/ext/mysqli/mysqli_api.c
+++ b/ext/mysqli/mysqli_api.c
@@ -780,7 +780,7 @@ PHP_FUNCTION(mysqli_fetch_lengths)
 /* {{{ Get a result row as an enumerated array */
 PHP_FUNCTION(mysqli_fetch_row)
 {
-	php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_NUM, 0);
+	php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_NUM);
 }
 /* }}} */

diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c
index 1e46aeedd93..1b973f40549 100644
--- a/ext/mysqli/mysqli_nonapi.c
+++ b/ext/mysqli/mysqli_nonapi.c
@@ -363,14 +363,14 @@ PHP_FUNCTION(mysqli_connect_error)
 /* {{{ Fetch a result row as an associative array, a numeric array, or both */
 PHP_FUNCTION(mysqli_fetch_array)
 {
-	php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
+	php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
 }
 /* }}} */

 /* {{{ Fetch a result row as an associative array */
 PHP_FUNCTION(mysqli_fetch_assoc)
 {
-	php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC, 0);
+	php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC);
 }
 /* }}} */

@@ -525,7 +525,52 @@ PHP_FUNCTION(mysqli_stmt_error_list)
 /* {{{ Fetch a result row as an object */
 PHP_FUNCTION(mysqli_fetch_object)
 {
-	php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_ASSOC, 1);
+	zval *mysql_result;
+	zend_class_entry *ce = NULL;
+	HashTable *ctor_params = NULL;
+
+	if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|Ch", &mysql_result, mysqli_result_class_entry, &ce, &ctor_params) == FAILURE) {
+		RETURN_THROWS();
+	}
+	if (ce == NULL) {
+		ce = zend_standard_class_def;
+	}
+	if (UNEXPECTED(ce->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_TRAIT|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS))) {
+		zend_throw_error(NULL, "Class %s cannot be instantiated", ZSTR_VAL(ce->name));
+		RETURN_THROWS();
+	}
+	if (!ce->constructor && ctor_params && zend_hash_num_elements(ctor_params) > 0) {
+		zend_argument_value_error(ERROR_ARG_POS(3),
+			"must be empty when the specified class (%s) does not have a constructor",
+			ZSTR_VAL(ce->name)
+		);
+		RETURN_THROWS();
+	}
+
+	MYSQL_RES *result;
+	MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, MYSQLI_STATUS_VALID);
+
+	zval dataset;
+	php_mysqli_fetch_into_hash_aux(&dataset, result, MYSQLI_ASSOC);
+
+	if (Z_TYPE(dataset) == IS_ARRAY) {
+		object_init_ex(return_value, ce);
+		HashTable *prop_table = zend_symtable_to_proptable(Z_ARR(dataset));
+		zval_ptr_dtor(&dataset);
+		if (!ce->default_properties_count && !ce->__set) {
+			Z_OBJ_P(return_value)->properties = prop_table;
+		} else {
+			zend_merge_properties(return_value, prop_table);
+			zend_array_release(prop_table);
+		}
+
+		if (ce->constructor) {
+			zend_call_known_function(ce->constructor, Z_OBJ_P(return_value), Z_OBJCE_P(return_value),
+				/* retval */ NULL, /* argc */ 0, /* params */ NULL, ctor_params);
+		}
+	} else {
+		RETURN_COPY_VALUE(&dataset);
+	}
 }
 /* }}} */

diff --git a/ext/mysqli/mysqli_priv.h b/ext/mysqli/mysqli_priv.h
index 97d9300a2b7..32602ef9498 100644
--- a/ext/mysqli/mysqli_priv.h
+++ b/ext/mysqli/mysqli_priv.h
@@ -47,7 +47,7 @@ extern void php_mysqli_dtor_p_elements(void *data);

 extern void php_mysqli_close(MY_MYSQL * mysql, int close_type, int resource_status);

-extern void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flag, int into_object);
+extern void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flag);
 extern void php_clear_stmt_bind(MY_STMT *stmt);
 extern void php_clear_mysql(MY_MYSQL *);
 extern MYSQLI_WARNING *php_get_warnings(MYSQLND_CONN_DATA * mysql);