Title: _wp_batch_split_terms
Published: August 18, 2015
Last modified: February 24, 2026

---

# _wp_batch_split_terms()

## In this article

 * [Source](https://developer.wordpress.org/reference/functions/_wp_batch_split_terms/?output_format=md#source)
 * [Related](https://developer.wordpress.org/reference/functions/_wp_batch_split_terms/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/functions/_wp_batch_split_terms/?output_format=md#changelog)

[ Back to top](https://developer.wordpress.org/reference/functions/_wp_batch_split_terms/?output_format=md#wp--skip-link--target)

Splits a batch of shared taxonomy terms.

## 󠀁[Source](https://developer.wordpress.org/reference/functions/_wp_batch_split_terms/?output_format=md#source)󠁿

    ```php
    function _wp_batch_split_terms() {
    	global $wpdb;

    	$lock_name = 'term_split.lock';

    	// Try to lock.
    	$lock_result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` ( `option_name`, `option_value`, `autoload` ) VALUES (%s, %s, 'off') /* LOCK */", $lock_name, time() ) );

    	if ( ! $lock_result ) {
    		$lock_result = get_option( $lock_name );

    		// Bail if we were unable to create a lock, or if the existing lock is still valid.
    		if ( ! $lock_result || ( $lock_result > ( time() - HOUR_IN_SECONDS ) ) ) {
    			wp_schedule_single_event( time() + ( 5 * MINUTE_IN_SECONDS ), 'wp_split_shared_term_batch' );
    			return;
    		}
    	}

    	// Update the lock, as by this point we've definitely got a lock, just need to fire the actions.
    	update_option( $lock_name, time() );

    	// Get a list of shared terms (those with more than one associated row in term_taxonomy).
    	$shared_terms = $wpdb->get_results(
    		"SELECT tt.term_id, t.*, count(*) as term_tt_count FROM {$wpdb->term_taxonomy} tt
    		 LEFT JOIN {$wpdb->terms} t ON t.term_id = tt.term_id
    		 GROUP BY t.term_id
    		 HAVING term_tt_count > 1
    		 LIMIT 10"
    	);

    	// No more terms, we're done here.
    	if ( ! $shared_terms ) {
    		update_option( 'finished_splitting_shared_terms', true );
    		delete_option( $lock_name );
    		return;
    	}

    	// Shared terms found? We'll need to run this script again.
    	wp_schedule_single_event( time() + ( 2 * MINUTE_IN_SECONDS ), 'wp_split_shared_term_batch' );

    	// Rekey shared term array for faster lookups.
    	$_shared_terms = array();
    	foreach ( $shared_terms as $shared_term ) {
    		$term_id                   = (int) $shared_term->term_id;
    		$_shared_terms[ $term_id ] = $shared_term;
    	}
    	$shared_terms = $_shared_terms;

    	// Get term taxonomy data for all shared terms.
    	$shared_term_ids = implode( ',', array_keys( $shared_terms ) );
    	$shared_tts      = $wpdb->get_results( "SELECT * FROM {$wpdb->term_taxonomy} WHERE `term_id` IN ({$shared_term_ids})" );

    	// Split term data recording is slow, so we do it just once, outside the loop.
    	$split_term_data    = get_option( '_split_terms', array() );
    	$skipped_first_term = array();
    	$taxonomies         = array();
    	foreach ( $shared_tts as $shared_tt ) {
    		$term_id = (int) $shared_tt->term_id;

    		// Don't split the first tt belonging to a given term_id.
    		if ( ! isset( $skipped_first_term[ $term_id ] ) ) {
    			$skipped_first_term[ $term_id ] = 1;
    			continue;
    		}

    		if ( ! isset( $split_term_data[ $term_id ] ) ) {
    			$split_term_data[ $term_id ] = array();
    		}

    		// Keep track of taxonomies whose hierarchies need flushing.
    		if ( ! isset( $taxonomies[ $shared_tt->taxonomy ] ) ) {
    			$taxonomies[ $shared_tt->taxonomy ] = 1;
    		}

    		// Split the term.
    		$split_term_data[ $term_id ][ $shared_tt->taxonomy ] = _split_shared_term( $shared_terms[ $term_id ], $shared_tt, false );
    	}

    	// Rebuild the cached hierarchy for each affected taxonomy.
    	foreach ( array_keys( $taxonomies ) as $tax ) {
    		delete_option( "{$tax}_children" );
    		_get_term_hierarchy( $tax );
    	}

    	update_option( '_split_terms', $split_term_data );

    	delete_option( $lock_name );
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-includes/taxonomy.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/6.9.4/src/wp-includes/taxonomy.php#L4401)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/6.9.4/src/wp-includes/taxonomy.php#L4401-L4488)

## 󠀁[Related](https://developer.wordpress.org/reference/functions/_wp_batch_split_terms/?output_format=md#related)󠁿

| Uses | Description | 
| [wp_schedule_single_event()](https://developer.wordpress.org/reference/functions/wp_schedule_single_event/)`wp-includes/cron.php` |

Schedules an event to run only once.

  | 
| [_get_term_hierarchy()](https://developer.wordpress.org/reference/functions/_get_term_hierarchy/)`wp-includes/taxonomy.php` |

Retrieves children of taxonomy as term IDs.

  | 
| [delete_option()](https://developer.wordpress.org/reference/functions/delete_option/)`wp-includes/option.php` |

Removes an option by name. Prevents removal of protected WordPress options.

  | 
| [wpdb::query()](https://developer.wordpress.org/reference/classes/wpdb/query/)`wp-includes/class-wpdb.php` |

Performs a database query, using current database connection.

  | 
| [update_option()](https://developer.wordpress.org/reference/functions/update_option/)`wp-includes/option.php` |

Updates the value of an option that was already added.

  | 
| [get_option()](https://developer.wordpress.org/reference/functions/get_option/)`wp-includes/option.php` |

Retrieves an option value based on an option name.

  | 
| [wpdb::get_results()](https://developer.wordpress.org/reference/classes/wpdb/get_results/)`wp-includes/class-wpdb.php` |

Retrieves an entire SQL result set from the database (i.e., many rows).

  | 
| [wpdb::prepare()](https://developer.wordpress.org/reference/classes/wpdb/prepare/)`wp-includes/class-wpdb.php` |

Prepares a SQL query for safe execution.

  |

[Show 4 more](https://developer.wordpress.org/reference/functions/_wp_batch_split_terms/?output_format=md#)
[Show less](https://developer.wordpress.org/reference/functions/_wp_batch_split_terms/?output_format=md#)

## 󠀁[Changelog](https://developer.wordpress.org/reference/functions/_wp_batch_split_terms/?output_format=md#changelog)󠁿

| Version | Description | 
| [4.3.0](https://developer.wordpress.org/reference/since/4.3.0/) | Introduced. |

## User Contributed Notes

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Ffunctions%2F_wp_batch_split_terms%2F)
before being able to contribute a note or feedback.