_wc_delete_transients()WC 9.8.0

Delete multiple transients in a single operation.

IMPORTANT: This is a private function (internal use ONLY).

This function efficiently deletes multiple transients at once, using a direct database query when possible for better performance.

Internal function — this function is designed to be used by the kernel itself. It is not recommended to use this function in your code.

No Hooks.

Return

true|false. True on success, false on failure.

Usage

_wc_delete_transients( $transients );
$transients(array) (required)
Array of transient names to delete (without the '_transient_' prefix).

Changelog

Since 9.8.0 Introduced.

_wc_delete_transients() code WC 9.8.1

function _wc_delete_transients( $transients ) {
	global $wpdb;

	if ( empty( $transients ) || ! is_array( $transients ) ) {
		return false;
	}

	// If using external object cache, delete each transient individually.
	if ( wp_using_ext_object_cache() ) {
		foreach ( $transients as $transient ) {
			delete_transient( $transient );
		}
		return true;
	} else {
		// For database storage, create a list of transient option names.
		$transient_names = array();
		foreach ( $transients as $transient ) {
			$transient_names[] = '_transient_' . $transient;
			$transient_names[] = '_transient_timeout_' . $transient;
		}

		// Limit the number of items in a single query to avoid exceeding database query parameter limits.
		if ( count( $transients ) > 199 ) {
			// Process in smaller chunks to reduce memory usage.
			$chunks  = array_chunk( $transients, 100 );
			$success = true;

			foreach ( $chunks as $chunk ) {
				$result = _wc_delete_transients( $chunk );
				if ( ! $result ) {
					$success = false;
				}
				// Force garbage collection after each chunk to free memory.
				gc_collect_cycles();
			}

			return $success;
		}

		try {
			// Before deleting, get the list of options to clear from cache.
			// Since we already have the option names we could skip this step but this mirrors WP's delete_option functionality.
			// It also allows us to only delete the options we know exist.
			$options_to_clear = array();
			if ( ! wp_installing() ) {
				$options_to_clear = $wpdb->get_col(
					$wpdb->prepare(
						'SELECT option_name FROM ' . $wpdb->options . ' WHERE option_name IN ( ' . implode( ', ', array_fill( 0, count( $transient_names ), '%s' ) ) . ' )',
						$transient_names
					)
				);
			}

			if ( empty( $options_to_clear ) ) {
				// If there are no options to clear, return true immediately.
				return true;
			}

			// Use a single query for better performance.
			$wpdb->query(
				$wpdb->prepare(
					'DELETE FROM ' . $wpdb->options . ' WHERE option_name IN ( ' . implode( ', ', array_fill( 0, count( $options_to_clear ), '%s' ) ) . ' )',
					$options_to_clear
				)
			);

			// Lets clear our options data from the cache.
			// We can batch delete if available, introduced in WP 6.0.0.
			if ( ! wp_installing() ) {
				if ( function_exists( 'wp_cache_delete_multiple' ) ) {
					wp_cache_delete_multiple( $options_to_clear, 'options' );
				} else {
					foreach ( $options_to_clear as $option_name ) {
						wp_cache_delete( $option_name, 'options' );
					}
				}

				// Also update alloptions cache if needed.
				// This is required to prevent phantom transients from being returned.
				$alloptions         = wp_load_alloptions( true );
				$updated_alloptions = false;

				if ( is_array( $alloptions ) ) {
					foreach ( $options_to_clear as $option_name ) {
						if ( isset( $alloptions[ $option_name ] ) ) {
							unset( $alloptions[ $option_name ] );
							$updated_alloptions = true;
						}
					}

					if ( $updated_alloptions ) {
						wp_cache_set( 'alloptions', $alloptions, 'options' );
					}
				}
			}

			return true;
		} catch ( Exception $e ) {
			wc_get_logger()->error(
				sprintf( 'Exception when deleting transients: %s', $e->getMessage() ),
				array( 'source' => '_wc_delete_transients' )
			);
			return false;
		}
	}
}