Last active
November 14, 2025 12:54
-
-
Save adamziel/51ac62858a97937a84a4c4b9e8dea463 to your computer and use it in GitHub Desktop.
Ship mysqli functions with sqlite
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "plugins": ["wp-staging"], | |
| "steps": [ | |
| { | |
| "step": "writeFile", | |
| "path": "/wordpress/wp-content/mu-plugins/shim_mysqli.php", | |
| "data": { | |
| "resource": "url", | |
| "url": "https://gist.githubusercontent.com/adamziel/51ac62858a97937a84a4c4b9e8dea463/raw/9185e69fc9e7d36f276e72aba92944107fd94bed/shim_mysqli.php" | |
| } | |
| } | |
| ] | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Plugin Name: SQLite MySQLi Shim (AST) | |
| * Description: Shims mysqli_* on top of sqlite-database-integration (AST driver). | |
| */ | |
| // Abort if not WordPress. | |
| if ( ! defined( 'ABSPATH' ) ) { | |
| // return; | |
| } | |
| // If real mysqli is present, do nothing. | |
| if ( extension_loaded( 'mysqli' ) || function_exists( 'mysqli_connect' ) ) { | |
| // return; | |
| } | |
| global $wpdb; | |
| // Only run when the SQLite integration is actually the DB driver. | |
| if ( ! isset( $wpdb ) || ! class_exists( 'WP_SQLite_DB' ) || ! ( $wpdb instanceof WP_SQLite_DB ) ) { | |
| // return; | |
| } | |
| // ---- Basic constants -------------------------------------------------------- | |
| if ( ! defined( 'MYSQLI_ASSOC' ) ) { | |
| define( 'MYSQLI_ASSOC', 1 ); | |
| } | |
| if ( ! defined( 'MYSQLI_NUM' ) ) { | |
| define( 'MYSQLI_NUM', 2 ); | |
| } | |
| if ( ! defined( 'MYSQLI_BOTH' ) ) { | |
| define( 'MYSQLI_BOTH', 3 ); | |
| } | |
| if ( ! defined( 'MYSQLI_STORE_RESULT' ) ) { | |
| define( 'MYSQLI_STORE_RESULT', 0 ); | |
| } | |
| if ( ! defined( 'MYSQLI_USE_RESULT' ) ) { | |
| define( 'MYSQLI_USE_RESULT', 1 ); | |
| } | |
| // ---- Helper functions ------------------------------------------------------- | |
| /** | |
| * Get the underlying WPDB / WP_SQLite_DB instance for a mysqli link. | |
| * | |
| * @param mixed $link | |
| * @return WP_SQLite_DB | |
| */ | |
| function sqlite_mysqli_shim_wpdb( $link = null ) { | |
| global $wpdb; | |
| if ( $link instanceof mysqli && isset( $link->wpdb ) ) { | |
| return $link->wpdb; | |
| } | |
| return $wpdb; | |
| } | |
| /** | |
| * Rough check if SQL is a result-returning statement. | |
| * | |
| * @param string $sql | |
| * @return bool | |
| */ | |
| function sqlite_mysqli_shim_is_select( $sql ) { | |
| return (bool) preg_match( '/^\s*(SELECT|SHOW|DESCRIBE|EXPLAIN)\s/i', ltrim( $sql ) ); | |
| } | |
| /** | |
| * Escape a value like mysqli_real_escape_string would. | |
| * | |
| * @param mixed $value | |
| * @return string | |
| */ | |
| function sqlite_mysqli_shim_escape( $value ) { | |
| if ( is_null( $value ) ) { | |
| return 'NULL'; | |
| } | |
| // Use WordPress' esc_sql if available. | |
| if ( function_exists( 'esc_sql' ) ) { | |
| return "'" . esc_sql( (string) $value ) . "'"; | |
| } | |
| return "'" . addslashes( (string) $value ) . "'"; | |
| } | |
| // ---- mysqli OO classes ------------------------------------------------------ | |
| class mysqli { | |
| /** @var WP_SQLite_DB */ | |
| public $wpdb; | |
| /** @var int */ | |
| public $connect_errno = 0; | |
| /** @var string */ | |
| public $connect_error = ''; | |
| /** @var int */ | |
| public $errno = 0; | |
| /** @var string */ | |
| public $error = ''; | |
| /** @var int */ | |
| public $affected_rows = 0; | |
| /** @var int|string */ | |
| public $insert_id = 0; | |
| /** | |
| * mysqli constructor. | |
| * | |
| * All connection params are ignored; connection is WordPress' `$wpdb`. | |
| */ | |
| public function __construct( | |
| ?string $host = null, | |
| ?string $username = null, | |
| ?string $passwd = null, | |
| ?string $dbname = null, | |
| ?int $port = null, | |
| ?string $socket = null | |
| ) { | |
| $this->wpdb = sqlite_mysqli_shim_wpdb(); | |
| $this->connect_errno = 0; | |
| $this->connect_error = ''; | |
| } | |
| public function query( string $query, int $resultmode = MYSQLI_STORE_RESULT ) { | |
| $result = mysqli_query( $this, $query, $resultmode ); | |
| $this->errno = mysqli_errno( $this ); | |
| $this->error = mysqli_error( $this ); | |
| $this->affected_rows = mysqli_affected_rows( $this ); | |
| $this->insert_id = mysqli_insert_id( $this ); | |
| return $result; | |
| } | |
| public function real_escape_string( string $string ): string { | |
| return mysqli_real_escape_string( $this, $string ); | |
| } | |
| public function close(): bool { | |
| return mysqli_close( $this ); | |
| } | |
| public function set_charset( string $charset ): bool { | |
| return mysqli_set_charset( $this, $charset ); | |
| } | |
| public function select_db( string $dbname ): bool { | |
| return mysqli_select_db( $this, $dbname ); | |
| } | |
| public function ping(): bool { | |
| return mysqli_ping( $this ); | |
| } | |
| public function prepare( string $query ) { | |
| return mysqli_prepare( $this, $query ); | |
| } | |
| } | |
| class mysqli_result { | |
| /** @var array<int,array<string,mixed>> */ | |
| public $rows = array(); | |
| /** @var int */ | |
| public $current_row = 0; | |
| /** @var int */ | |
| public $num_rows = 0; | |
| /** | |
| * @param array<int,array<string,mixed>> $rows | |
| */ | |
| public function __construct( array $rows ) { | |
| $this->rows = array_values( $rows ); | |
| $this->num_rows = count( $this->rows ); | |
| $this->current_row = 0; | |
| } | |
| public function fetch_assoc() { | |
| return mysqli_fetch_assoc( $this ); | |
| } | |
| public function fetch_array( int $resulttype = MYSQLI_BOTH ) { | |
| return mysqli_fetch_array( $this, $resulttype ); | |
| } | |
| public function fetch_row() { | |
| return mysqli_fetch_row( $this ); | |
| } | |
| public function fetch_object( string $class_name = 'stdClass', array $params = array() ) { | |
| return mysqli_fetch_object( $this, $class_name, $params ); | |
| } | |
| public function data_seek( int $offset ): bool { | |
| if ( $offset < 0 || $offset >= $this->num_rows ) { | |
| return false; | |
| } | |
| $this->current_row = $offset; | |
| return true; | |
| } | |
| public function free(): void { | |
| $this->rows = array(); | |
| $this->num_rows = 0; | |
| $this->current_row = 0; | |
| } | |
| } | |
| class mysqli_stmt { | |
| /** @var mysqli */ | |
| public $mysqli; | |
| /** @var string */ | |
| public $query; | |
| /** @var string */ | |
| public $types = ''; | |
| /** @var array<int,mixed> */ | |
| public $params = array(); | |
| /** @var int */ | |
| public $affected_rows = 0; | |
| /** @var int|string */ | |
| public $insert_id = 0; | |
| /** @var mysqli_result|null */ | |
| public $result = null; | |
| /** @var int */ | |
| public $errno = 0; | |
| /** @var string */ | |
| public $error = ''; | |
| public function __construct( mysqli $link, string $query ) { | |
| $this->mysqli = $link; | |
| $this->query = $query; | |
| } | |
| public function bind_param( string $types, &...$vars ): bool { | |
| $this->types = $types; | |
| $this->params = &$vars; | |
| return true; | |
| } | |
| /** | |
| * Very simple emulation: translate "?" placeholders to %s/%d and use $wpdb->prepare(). | |
| */ | |
| protected function build_query(): string { | |
| $query = $this->query; | |
| $placeholders = array(); | |
| $args = array(); | |
| $len = strlen( $this->types ); | |
| for ( $i = 0; $i < $len; $i++ ) { | |
| $t = $this->types[ $i ]; | |
| $placeholders[] = ( $t === 'i' || $t === 'd' ) ? '%d' : '%s'; | |
| if ( array_key_exists( $i, $this->params ) ) { | |
| $args[] = $this->params[ $i ]; | |
| } | |
| } | |
| $parts = explode( '?', $query ); | |
| if ( count( $parts ) - 1 !== count( $placeholders ) ) { | |
| // Fallback: just let WPDB deal with any existing % placeholders. | |
| return $query; | |
| } | |
| $rebuilt = array_shift( $parts ); | |
| foreach ( $placeholders as $idx => $ph ) { | |
| $rebuilt .= $ph . $parts[ $idx ]; | |
| } | |
| $wpdb = sqlite_mysqli_shim_wpdb(); | |
| array_unshift( $args, $rebuilt ); | |
| return $wpdb->prepare( ...$args ); | |
| } | |
| public function execute(): bool { | |
| $sql = $this->build_query(); | |
| $result = mysqli_query( $this->mysqli, $sql ); | |
| $this->errno = mysqli_errno( $this->mysqli ); | |
| $this->error = mysqli_error( $this->mysqli ); | |
| $this->affected_rows = mysqli_affected_rows( $this->mysqli ); | |
| $this->insert_id = mysqli_insert_id( $this->mysqli ); | |
| if ( $result instanceof mysqli_result ) { | |
| $this->result = $result; | |
| } else { | |
| $this->result = null; | |
| } | |
| return $this->errno === 0; | |
| } | |
| public function get_result(): ?mysqli_result { | |
| return $this->result; | |
| } | |
| public function close(): bool { | |
| $this->result = null; | |
| return true; | |
| } | |
| } | |
| // ---- Procedural mysqli_* API ----------------------------------------------- | |
| // Connection / basic info ----------------------------------------------------- | |
| if ( ! function_exists( 'mysqli_connect' ) ) { | |
| function mysqli_connect( | |
| $host = null, | |
| $username = null, | |
| $passwd = null, | |
| $dbname = null, | |
| $port = null, | |
| $socket = null | |
| ) { | |
| return new mysqli( $host, $username, $passwd, $dbname, $port, $socket ); | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_close' ) ) { | |
| function mysqli_close( $link ): bool { | |
| // Nothing real to close, SQLite connection is shared. | |
| return true; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_connect_errno' ) ) { | |
| function mysqli_connect_errno(): int { | |
| // We don't have a real remote connection; treat as always ok. | |
| return 0; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_connect_error' ) ) { | |
| function mysqli_connect_error(): ?string { | |
| return null; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_select_db' ) ) { | |
| function mysqli_select_db( $link, $dbname ): bool { | |
| // Single SQLite DB, nothing to switch. | |
| return true; | |
| } | |
| } | |
| // Query execution ------------------------------------------------------------- | |
| if ( ! function_exists( 'mysqli_query' ) ) { | |
| function mysqli_query( $link, string $query, int $resultmode = MYSQLI_STORE_RESULT ) { | |
| $wpdb = sqlite_mysqli_shim_wpdb( $link ); | |
| if ( method_exists( $wpdb, 'db_connect' ) ) { | |
| $wpdb->db_connect(); | |
| } | |
| if ( sqlite_mysqli_shim_is_select( $query ) ) { | |
| $rows = $wpdb->get_results( $query, ARRAY_A ); | |
| if ( $rows === null ) { | |
| return false; | |
| } | |
| return new mysqli_result( $rows ); | |
| } | |
| $res = $wpdb->query( $query ); | |
| if ( false === $res ) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_real_query' ) ) { | |
| function mysqli_real_query( $link, string $query ): bool { | |
| $result = mysqli_query( $link, $query, MYSQLI_STORE_RESULT ); | |
| return $result !== false; | |
| } | |
| } | |
| // Very naive multi-query: split on ';' and run sequentially. | |
| $GLOBALS['sqlite_mysqli_multi_last_result'] = null; | |
| if ( ! function_exists( 'mysqli_multi_query' ) ) { | |
| function mysqli_multi_query( $link, string $query ): bool { | |
| $wpdb = sqlite_mysqli_shim_wpdb( $link ); | |
| $queries = array_filter( array_map( 'trim', explode( ';', $query ) ) ); | |
| $last_result = null; | |
| foreach ( $queries as $sql ) { | |
| if ( $sql === '' ) { | |
| continue; | |
| } | |
| if ( sqlite_mysqli_shim_is_select( $sql ) ) { | |
| $rows = $wpdb->get_results( $sql, ARRAY_A ); | |
| if ( $rows === null ) { | |
| return false; | |
| } | |
| $last_result = new mysqli_result( $rows ); | |
| } else { | |
| $res = $wpdb->query( $sql ); | |
| if ( false === $res ) { | |
| return false; | |
| } | |
| $last_result = true; | |
| } | |
| } | |
| $GLOBALS['sqlite_mysqli_multi_last_result'] = $last_result; | |
| return true; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_store_result' ) ) { | |
| function mysqli_store_result( $link = null ) { | |
| $res = $GLOBALS['sqlite_mysqli_multi_last_result'] ?? null; | |
| return $res instanceof mysqli_result ? $res : null; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_use_result' ) ) { | |
| function mysqli_use_result( $link = null ) { | |
| return mysqli_store_result( $link ); | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_next_result' ) ) { | |
| function mysqli_next_result( $link = null ): bool { | |
| // We don't track multiple result sets, so always false. | |
| return false; | |
| } | |
| } | |
| // Result fetching ------------------------------------------------------------- | |
| if ( ! function_exists( 'mysqli_num_rows' ) ) { | |
| function mysqli_num_rows( $result ): int { | |
| if ( $result instanceof mysqli_result ) { | |
| return $result->num_rows; | |
| } | |
| return 0; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_fetch_assoc' ) ) { | |
| function mysqli_fetch_assoc( $result ) { | |
| if ( ! ( $result instanceof mysqli_result ) ) { | |
| return null; | |
| } | |
| if ( $result->current_row >= $result->num_rows ) { | |
| return null; | |
| } | |
| $row = $result->rows[ $result->current_row ]; | |
| $result->current_row++; | |
| return $row; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_fetch_row' ) ) { | |
| function mysqli_fetch_row( $result ) { | |
| $assoc = mysqli_fetch_assoc( $result ); | |
| if ( $assoc === null ) { | |
| return null; | |
| } | |
| return array_values( $assoc ); | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_fetch_array' ) ) { | |
| function mysqli_fetch_array( $result, int $resulttype = MYSQLI_BOTH ) { | |
| $assoc = mysqli_fetch_assoc( $result ); | |
| if ( $assoc === null ) { | |
| return null; | |
| } | |
| if ( MYSQLI_ASSOC === $resulttype ) { | |
| return $assoc; | |
| } | |
| $num = array_values( $assoc ); | |
| if ( MYSQLI_NUM === $resulttype ) { | |
| return $num; | |
| } | |
| // MYSQLI_BOTH. | |
| $both = $num; | |
| foreach ( $assoc as $key => $value ) { | |
| $both[ $key ] = $value; | |
| } | |
| return $both; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_fetch_object' ) ) { | |
| function mysqli_fetch_object( $result, string $class_name = 'stdClass', array $params = array() ) { | |
| $assoc = mysqli_fetch_assoc( $result ); | |
| if ( $assoc === null ) { | |
| return null; | |
| } | |
| if ( 'stdClass' === $class_name && empty( $params ) ) { | |
| return (object) $assoc; | |
| } | |
| $obj = new $class_name( ...$params ); | |
| foreach ( $assoc as $k => $v ) { | |
| $obj->{$k} = $v; | |
| } | |
| return $obj; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_fetch_all' ) ) { | |
| function mysqli_fetch_all( $result, int $resulttype = MYSQLI_BOTH ): array { | |
| $rows = array(); | |
| while ( null !== ( $row = mysqli_fetch_array( $result, $resulttype ) ) ) { | |
| $rows[] = $row; | |
| } | |
| return $rows; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_free_result' ) ) { | |
| function mysqli_free_result( $result ): void { | |
| if ( $result instanceof mysqli_result ) { | |
| $result->free(); | |
| } | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_data_seek' ) ) { | |
| function mysqli_data_seek( $result, int $offset ): bool { | |
| if ( $result instanceof mysqli_result ) { | |
| return $result->data_seek( $offset ); | |
| } | |
| return false; | |
| } | |
| } | |
| // Error / info --------------------------------------------------------------- | |
| if ( ! function_exists( 'mysqli_error' ) ) { | |
| function mysqli_error( $link = null ): string { | |
| $wpdb = sqlite_mysqli_shim_wpdb( $link ); | |
| return (string) ( $wpdb->last_error ?? '' ); | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_errno' ) ) { | |
| function mysqli_errno( $link = null ): int { | |
| $wpdb = sqlite_mysqli_shim_wpdb( $link ); | |
| if ( ! empty( $wpdb->last_error ) ) { | |
| // Generic client-side error code. | |
| return 2000; | |
| } | |
| return 0; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_insert_id' ) ) { | |
| function mysqli_insert_id( $link = null ) { | |
| $wpdb = sqlite_mysqli_shim_wpdb( $link ); | |
| return $wpdb->insert_id; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_affected_rows' ) ) { | |
| function mysqli_affected_rows( $link = null ): int { | |
| $wpdb = sqlite_mysqli_shim_wpdb( $link ); | |
| return (int) $wpdb->rows_affected; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_field_count' ) ) { | |
| function mysqli_field_count( $link = null ): int { | |
| $wpdb = sqlite_mysqli_shim_wpdb( $link ); | |
| if ( isset( $wpdb->dbh ) && $wpdb->dbh instanceof WP_SQLite_Driver ) { | |
| return $wpdb->dbh->get_last_column_count(); | |
| } | |
| if ( is_array( $wpdb->last_result ) && ! empty( $wpdb->last_result ) ) { | |
| $first = $wpdb->last_result[0]; | |
| return count( get_object_vars( $first ) ); | |
| } | |
| return 0; | |
| } | |
| } | |
| // Escaping / charset --------------------------------------------------------- | |
| if ( ! function_exists( 'mysqli_real_escape_string' ) ) { | |
| function mysqli_real_escape_string( $link, string $string ): string { | |
| // Escape only, don't wrap in quotes. | |
| if ( function_exists( 'esc_sql' ) ) { | |
| return esc_sql( $string ); | |
| } | |
| return addslashes( $string ); | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_set_charset' ) ) { | |
| function mysqli_set_charset( $link, string $charset ): bool { | |
| $wpdb = sqlite_mysqli_shim_wpdb( $link ); | |
| if ( method_exists( $wpdb, 'set_charset' ) ) { | |
| $wpdb->set_charset( null, $charset ); | |
| } | |
| return true; | |
| } | |
| } | |
| // Server / client info -------------------------------------------------------- | |
| if ( ! function_exists( 'mysqli_get_server_info' ) ) { | |
| function mysqli_get_server_info( $link = null ): string { | |
| $wpdb = sqlite_mysqli_shim_wpdb( $link ); | |
| // WP_SQLite_DB::db_version() returns a MySQL-like version string. | |
| return method_exists( $wpdb, 'db_version' ) ? $wpdb->db_version() : '8.0'; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_get_client_info' ) ) { | |
| function mysqli_get_client_info( $link = null ): string { | |
| // Arbitrary string; some libs only display it. | |
| return 'SQLite via sqlite-database-integration (AST)'; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_get_host_info' ) ) { | |
| function mysqli_get_host_info( $link = null ): string { | |
| return 'SQLite (file-based) via sqlite-database-integration'; | |
| } | |
| } | |
| // Ping / transactions (best-effort / mostly no-op) --------------------------- | |
| if ( ! function_exists( 'mysqli_ping' ) ) { | |
| function mysqli_ping( $link = null ): bool { | |
| // SQLite connection is local process, assume it's fine. | |
| return true; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_autocommit' ) ) { | |
| function mysqli_autocommit( $link, bool $mode ): bool { | |
| // AST driver manages its own transactions; we don't mirror autocommit. | |
| return true; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_begin_transaction' ) ) { | |
| function mysqli_begin_transaction( $link, int $flags = 0, ?string $name = null ): bool { | |
| $wpdb = sqlite_mysqli_shim_wpdb( $link ); | |
| $wpdb->query( 'START TRANSACTION' ); | |
| return true; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_commit' ) ) { | |
| function mysqli_commit( $link, int $flags = 0, ?string $name = null ): bool { | |
| $wpdb = sqlite_mysqli_shim_wpdb( $link ); | |
| $wpdb->query( 'COMMIT' ); | |
| return true; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_rollback' ) ) { | |
| function mysqli_rollback( $link, int $flags = 0, ?string $name = null ): bool { | |
| $wpdb = sqlite_mysqli_shim_wpdb( $link ); | |
| $wpdb->query( 'ROLLBACK' ); | |
| return true; | |
| } | |
| } | |
| // Prepared statements (procedural) ------------------------------------------- | |
| if ( ! function_exists( 'mysqli_prepare' ) ) { | |
| function mysqli_prepare( $link, string $query ) { | |
| $link = $link instanceof mysqli ? $link : new mysqli(); | |
| return new mysqli_stmt( $link, $query ); | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_stmt_bind_param' ) ) { | |
| function mysqli_stmt_bind_param( $stmt, string $types, &...$vars ): bool { | |
| if ( ! ( $stmt instanceof mysqli_stmt ) ) { | |
| return false; | |
| } | |
| return $stmt->bind_param( $types, ...$vars ); | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_stmt_execute' ) ) { | |
| function mysqli_stmt_execute( $stmt ): bool { | |
| if ( ! ( $stmt instanceof mysqli_stmt ) ) { | |
| return false; | |
| } | |
| return $stmt->execute(); | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_stmt_get_result' ) ) { | |
| function mysqli_stmt_get_result( $stmt ) { | |
| if ( ! ( $stmt instanceof mysqli_stmt ) ) { | |
| return false; | |
| } | |
| return $stmt->get_result(); | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_stmt_close' ) ) { | |
| function mysqli_stmt_close( $stmt ): bool { | |
| if ( ! ( $stmt instanceof mysqli_stmt ) ) { | |
| return false; | |
| } | |
| return $stmt->close(); | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_stmt_errno' ) ) { | |
| function mysqli_stmt_errno( $stmt ): int { | |
| if ( ! ( $stmt instanceof mysqli_stmt ) ) { | |
| return 0; | |
| } | |
| return $stmt->errno; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_stmt_error' ) ) { | |
| function mysqli_stmt_error( $stmt ): string { | |
| if ( ! ( $stmt instanceof mysqli_stmt ) ) { | |
| return ''; | |
| } | |
| return $stmt->error; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_stmt_affected_rows' ) ) { | |
| function mysqli_stmt_affected_rows( $stmt ): int { | |
| if ( ! ( $stmt instanceof mysqli_stmt ) ) { | |
| return 0; | |
| } | |
| return (int) $stmt->affected_rows; | |
| } | |
| } | |
| if ( ! function_exists( 'mysqli_stmt_insert_id' ) ) { | |
| function mysqli_stmt_insert_id( $stmt ) { | |
| if ( ! ( $stmt instanceof mysqli_stmt ) ) { | |
| return 0; | |
| } | |
| return $stmt->insert_id; | |
| } | |
| } | |
| // Everything else (debug, stats, etc.) can be added here as needed, either | |
| // as thin wrappers or safe no-ops to satisfy plugins expecting them. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment