@@ -606,7 +606,6 @@ public function query( $args, $assoc_args ) {
606606 }
607607
608608 WP_CLI ::debug ( 'MySQL/MariaDB binary not available, falling back to wpdb. ' , 'db ' );
609- $ this ->maybe_load_wpdb ();
610609 $ this ->wpdb_query ( $ query , $ assoc_args );
611610 return ;
612611 }
@@ -958,7 +957,6 @@ public function import( $args, $assoc_args ) {
958957 }
959958
960959 WP_CLI ::debug ( 'MySQL/MariaDB binary not available, falling back to wpdb for import. ' , 'db ' );
961- $ this ->maybe_load_wpdb ();
962960 $ this ->wpdb_import ( (string ) $ sql_content , $ assoc_args );
963961 WP_CLI ::success ( sprintf ( "Imported from '%s'. " , $ result_file ) );
964962 return ;
@@ -1969,37 +1967,8 @@ private static function get_create_query() {
19691967 * @param string $query SQL query to execute.
19701968 */
19711969 protected function run_query_via_mysqli ( $ query ) {
1972- $ db_host = DB_HOST ;
1973- $ port = null ;
1974- $ socket = null ;
1975-
1976- if ( ': ' === substr ( $ db_host , 0 , 1 ) ) {
1977- $ socket = substr ( $ db_host , 1 );
1978- $ db_host = 'localhost ' ;
1979- } else {
1980- $ parts = explode ( ': ' , $ db_host , 2 );
1981- $ db_host = $ parts [0 ];
1982- if ( isset ( $ parts [1 ] ) ) {
1983- $ port_or_socket = trim ( $ parts [1 ] );
1984- if ( '' !== $ port_or_socket && '/ ' === $ port_or_socket [0 ] ) {
1985- $ socket = $ port_or_socket ;
1986- } elseif ( '' !== $ port_or_socket ) {
1987- $ port = (int ) $ port_or_socket ;
1988- }
1989- }
1990- }
1991-
1992- // When using a socket, pass 0 for port. When a port is explicitly set, use it; otherwise use the default.
1993- $ port_value = null !== $ port ? $ port : 0 ;
1994- $ socket_value = null !== $ socket ? $ socket : '' ;
1995-
1996- // No database is selected intentionally — DDL operations like DROP/CREATE DATABASE work at the server level.
1997- // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__mysqli -- direct mysqli required as wpdb fallback when mysql binary is unavailable.
1998- $ conn = new mysqli ( $ db_host , DB_USER , DB_PASSWORD , '' , $ port_value , $ socket_value );
1999-
2000- if ( $ conn ->connect_errno ) {
2001- WP_CLI ::error ( sprintf ( 'Failed to connect to the database: %s ' , $ conn ->connect_error ) );
2002- }
1970+ // No database selected — DDL operations like DROP/CREATE DATABASE work at the server level.
1971+ $ conn = $ this ->get_db_connection ( false );
20031972
20041973 if ( ! $ conn ->query ( $ query ) ) {
20051974 $ error = $ conn ->error ;
@@ -2507,140 +2476,116 @@ protected function is_mysql_binary_available() {
25072476 }
25082477
25092478 /**
2510- * Load WordPress's wpdb if not already available.
2479+ * Open a mysqli connection using the WordPress database credentials.
2480+ *
2481+ * Used as a fallback when the mysql/mariadb binary is not available.
2482+ * Parses DB_HOST the same way WordPress does (host:port, host:/socket, :/socket).
25112483 *
2512- * Loads the minimal required WordPress files to make $wpdb available,
2513- * including any db.php drop-in (e.g., HyperDB or other custom drivers).
2484+ * @param bool $select_db Whether to select DB_NAME on connect. Pass false for
2485+ * server-level DDL (DROP/CREATE DATABASE).
2486+ * @return mysqli Connected mysqli instance. Calls WP_CLI::error() on failure.
25142487 */
2515- protected function maybe_load_wpdb () {
2516- global $ wpdb ;
2517-
2518- if ( isset ( $ wpdb ) ) {
2519- return ;
2520- }
2521-
2522- if ( ! defined ( 'WPINC ' ) ) {
2523- // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
2524- define ( 'WPINC ' , 'wp-includes ' );
2525- }
2526-
2527- if ( ! defined ( 'WP_CONTENT_DIR ' ) ) {
2528- define ( 'WP_CONTENT_DIR ' , ABSPATH . 'wp-content ' );
2529- }
2488+ protected function get_db_connection ( $ select_db = true ) {
2489+ $ db_host = DB_HOST ;
2490+ $ port = null ;
2491+ $ socket = null ;
25302492
2531- // Load prerequisite files if not already loaded.
2532- if ( ! function_exists ( 'add_action ' ) ) {
2533- foreach ( [ 'load.php ' , 'compat.php ' , 'plugin.php ' ] as $ file ) {
2534- $ path = ABSPATH . WPINC . '/ ' . $ file ;
2535- if ( file_exists ( $ path ) ) {
2536- require_once $ path ;
2493+ if ( ': ' === substr ( $ db_host , 0 , 1 ) ) {
2494+ $ socket = substr ( $ db_host , 1 );
2495+ $ db_host = 'localhost ' ;
2496+ } else {
2497+ $ parts = explode ( ': ' , $ db_host , 2 );
2498+ $ db_host = $ parts [0 ];
2499+ if ( isset ( $ parts [1 ] ) ) {
2500+ $ port_or_socket = trim ( $ parts [1 ] );
2501+ if ( '' !== $ port_or_socket && '/ ' === $ port_or_socket [0 ] ) {
2502+ $ socket = $ port_or_socket ;
2503+ } elseif ( '' !== $ port_or_socket ) {
2504+ $ port = (int ) $ port_or_socket ;
25372505 }
25382506 }
25392507 }
25402508
2541- // Load class-wpdb.php if the wpdb class is not yet available.
2542- // This is checked independently of add_action, since WP-CLI's config loading
2543- // may have already loaded plugin.php (defining add_action) without loading wpdb.
2544- if ( ! class_exists ( 'wpdb ' ) ) {
2545- // Defines `wp_debug_backtrace_summary()` as used by wpdb.
2546- if ( ! function_exists ( 'wp_debug_backtrace_summary ' ) ) {
2547- $ functions_file = ABSPATH . WPINC . '/functions.php ' ;
2548- if ( file_exists ( $ functions_file ) ) {
2549- require_once $ functions_file ;
2550- }
2551- }
2509+ $ port_value = null !== $ port ? $ port : 0 ;
2510+ $ socket_value = null !== $ socket ? $ socket : '' ;
2511+ $ database = $ select_db ? DB_NAME : '' ;
25522512
2553- $ wpdb_file = ABSPATH . WPINC . '/class-wpdb.php ' ;
2554- if ( file_exists ( $ wpdb_file ) ) {
2555- require_once $ wpdb_file ;
2556- }
2557- }
2513+ // phpcs:ignore WordPress.DB.RestrictedClasses.mysql__mysqli -- direct mysqli required as fallback when mysql binary is unavailable.
2514+ $ conn = new mysqli ( $ db_host , DB_USER , DB_PASSWORD , $ database , $ port_value , $ socket_value );
25582515
2559- // Load db.php drop-in if it exists (e.g., HyperDB or other custom drivers).
2560- $ db_dropin_path = WP_CONTENT_DIR . '/db.php ' ;
2561- if ( file_exists ( $ db_dropin_path ) && ! $ this ->is_sqlite () ) {
2562- require_once $ db_dropin_path ;
2516+ if ( $ conn ->connect_errno ) {
2517+ WP_CLI ::error ( sprintf ( 'Failed to connect to the database: %s ' , $ conn ->connect_error ) );
25632518 }
25642519
2565- // If $wpdb is still not set (e.g. no drop-in), create a new instance using the DB credentials from wp-config.php.
2566- if ( ! isset ( $ GLOBALS ['wpdb ' ] ) && class_exists ( 'wpdb ' ) ) {
2567- // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
2568- $ wpdb = new wpdb ( DB_USER , DB_PASSWORD , DB_NAME , DB_HOST );
2569- if ( isset ( $ GLOBALS ['table_prefix ' ] ) && is_string ( $ GLOBALS ['table_prefix ' ] ) ) {
2570- $ wpdb ->set_prefix ( $ GLOBALS ['table_prefix ' ] );
2571- }
2572- }
2520+ return $ conn ;
25732521 }
25742522
25752523 /**
2576- * Execute a query against the database using wpdb .
2524+ * Execute a query against the database using mysqli .
25772525 *
25782526 * Used as a fallback when the mysql/mariadb binary is not available.
2527+ * Outputs results in the same tab-separated format as the mysql binary.
25792528 *
25802529 * @param string $query SQL query to execute.
25812530 * @param array $assoc_args Associative arguments.
25822531 */
25832532 protected function wpdb_query ( $ query , $ assoc_args = [] ) {
2584- global $ wpdb ;
2585-
2586- if ( ! isset ( $ wpdb ) || ! ( $ wpdb instanceof wpdb ) ) {
2587- WP_CLI ::error ( 'WordPress database (wpdb) is not available. Please install MySQL or MariaDB client tools. ' );
2588- }
2533+ $ conn = $ this ->get_db_connection ();
25892534
2590- $ skip_column_names = Utils \get_flag_value ( $ assoc_args , 'skip-column-names ' , false );
2591-
2592- $ is_row_modifying_query = preg_match ( '/\b(UPDATE|DELETE|INSERT|REPLACE(?!\s*\()|LOAD DATA)\b/i ' , $ query );
2535+ $ skip_column_names = Utils \get_flag_value ( $ assoc_args , 'skip-column-names ' , false );
2536+ $ is_row_modifying_query = (bool ) preg_match ( '/\b(UPDATE|DELETE|INSERT|REPLACE(?!\s*\()|LOAD DATA)\b/i ' , $ query );
25932537
25942538 if ( $ is_row_modifying_query ) {
2595- // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2596- $ affected_rows = $ wpdb ->query ( $ query );
2597- if ( false === $ affected_rows ) {
2598- // phpcs:ignore WordPress.WP.AlternativeFunctions.strip_tags_strip_tags
2599- WP_CLI ::error ( 'Query failed: ' . strip_tags ( $ wpdb ->last_error ) );
2539+ if ( ! $ conn ->query ( $ query ) ) {
2540+ $ error = $ conn ->error ;
2541+ $ conn ->close ();
2542+ WP_CLI ::error ( "Query failed: {$ error }" );
26002543 }
2544+ $ affected_rows = $ conn ->affected_rows ;
2545+ $ conn ->close ();
26012546 WP_CLI ::success ( "Query succeeded. Rows affected: {$ affected_rows }" );
26022547 } else {
2603- // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2604- $ results = $ wpdb ->get_results ( $ query , ARRAY_A );
2605-
2606- if ( $ wpdb ->last_error ) {
2607- // phpcs:ignore WordPress.WP.AlternativeFunctions.strip_tags_strip_tags
2608- WP_CLI ::error ( 'Query failed: ' . strip_tags ( $ wpdb ->last_error ) );
2548+ $ result = $ conn ->query ( $ query );
2549+ if ( ! $ result ) {
2550+ $ error = $ conn ->error ;
2551+ $ conn ->close ();
2552+ WP_CLI ::error ( "Query failed: {$ error }" );
26092553 }
26102554
2611- if ( empty ( $ results ) ) {
2612- return ;
2555+ if ( $ result instanceof mysqli_result ) {
2556+ $ fields = $ result ->fetch_fields ();
2557+ $ headers = $ fields ? array_column ( (array ) $ fields , 'name ' ) : [];
2558+ if ( ! $ skip_column_names && ! empty ( $ headers ) ) {
2559+ WP_CLI ::line ( implode ( "\t" , $ headers ) );
2560+ }
2561+ $ all_rows = $ result ->fetch_all ( MYSQLI_NUM );
2562+ foreach ( $ all_rows as $ row ) {
2563+ WP_CLI ::line ( implode ( "\t" , array_map ( 'strval ' , $ row ) ) );
2564+ }
2565+ $ result ->free ();
26132566 }
26142567
2615- $ headers = array_keys ( $ results [0 ] );
2616- $ this ->display_query_results ( $ headers , $ results , $ skip_column_names );
2568+ $ conn ->close ();
26172569 }
26182570 }
26192571
26202572 /**
2621- * Import SQL content into the database using wpdb .
2573+ * Import SQL content into the database using mysqli .
26222574 *
26232575 * Used as a fallback when the mysql/mariadb binary is not available.
26242576 *
26252577 * @param string $sql_content SQL content to import.
26262578 * @param array $assoc_args Associative arguments.
26272579 */
26282580 protected function wpdb_import ( $ sql_content , $ assoc_args = [] ) {
2629- global $ wpdb ;
2630-
2631- if ( ! isset ( $ wpdb ) || ! ( $ wpdb instanceof wpdb ) ) {
2632- WP_CLI ::error ( 'WordPress database (wpdb) is not available. Please install MySQL or MariaDB client tools. ' );
2633- }
2581+ $ conn = $ this ->get_db_connection ();
26342582
26352583 $ skip_optimization = Utils \get_flag_value ( $ assoc_args , 'skip-optimization ' , false );
26362584
26372585 if ( ! $ skip_optimization ) {
2638- // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2639- $ wpdb ->query ( 'SET autocommit = 0 ' );
2640- // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2641- $ wpdb ->query ( 'SET unique_checks = 0 ' );
2642- // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2643- $ wpdb ->query ( 'SET foreign_key_checks = 0 ' );
2586+ $ conn ->query ( 'SET autocommit = 0 ' );
2587+ $ conn ->query ( 'SET unique_checks = 0 ' );
2588+ $ conn ->query ( 'SET foreign_key_checks = 0 ' );
26442589 }
26452590
26462591 $ statements = $ this ->split_sql_statements ( $ sql_content );
@@ -2650,28 +2595,24 @@ protected function wpdb_import( $sql_content, $assoc_args = [] ) {
26502595 if ( '' === $ statement ) {
26512596 continue ;
26522597 }
2653- // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2654- $ result = $ wpdb ->query ( $ statement );
2655- if ( false === $ result ) {
2598+ if ( ! $ conn ->query ( $ statement ) ) {
2599+ $ error = $ conn ->error ;
26562600 if ( ! $ skip_optimization ) {
2657- // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2658- $ wpdb ->query ( 'ROLLBACK ' );
2601+ $ conn ->query ( 'ROLLBACK ' );
26592602 }
2660- // phpcs:ignore WordPress.WP.AlternativeFunctions.strip_tags_strip_tags
2661- WP_CLI ::error ( ' Import failed: ' . strip_tags ( $ wpdb -> last_error ) );
2603+ $ conn -> close ();
2604+ WP_CLI ::error ( " Import failed: { $ error }" );
26622605 }
26632606 }
26642607
26652608 if ( ! $ skip_optimization ) {
2666- // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2667- $ wpdb ->query ( 'COMMIT ' );
2668- // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2669- $ wpdb ->query ( 'SET autocommit = 1 ' );
2670- // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2671- $ wpdb ->query ( 'SET unique_checks = 1 ' );
2672- // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
2673- $ wpdb ->query ( 'SET foreign_key_checks = 1 ' );
2609+ $ conn ->query ( 'COMMIT ' );
2610+ $ conn ->query ( 'SET autocommit = 1 ' );
2611+ $ conn ->query ( 'SET unique_checks = 1 ' );
2612+ $ conn ->query ( 'SET foreign_key_checks = 1 ' );
26742613 }
2614+
2615+ $ conn ->close ();
26752616 }
26762617
26772618 /**
0 commit comments