I have done this before, but I warn you that this is something to avoid doing. It is best when you have a very limited number of terms that don’t change.
With the warning over, here is how to do it. You need create a rewrite rule with the term slugs in it to not break your rewrite rules. If you use a catch all, then it will break the rewrite rules for your pages.
function my_custom_rewrite_rules_array( $rules ) {
global $wp_rewrite;
// Generate the regexp for the terms
$terms = get_terms( 'Speaker', array( 'hide_empty' => false ) );
$term_slugs = array();
foreach ( $terms as $term ) {
$term_slugs[] = preg_quote( $term->slug );
}
// (term1-slug|term2-slug|term3-slug)
$terms_regexp = '(' . implode( '|', $term_slugs ) . ')';
// add_rewrite_tag( $tagname, $regex, $query )
$wp_rewrite->add_rewrite_tag( "%speaker%", $terms_regexp, "taxonomy=speaker&term=" );
// Use generate_rewrite_rules to make the various rules for pagination and other endpoints
$speaker_rules = $wp_rewrite->generate_rewrite_rules( '/%speaker%/' );
// Add our speaker rules
return $speaker_rules + $rules;
}
add_filter( 'rewrite_rules_array', 'my_custom_rewrite_rules_array' );
As you may see, the downside of this is the rewrite rules need to be updated each time a new term is created. We can rebuild the rules whenever a change happens.
add_action( 'created_term', 'my_custom_flush_rewrite_rules', 10, 3 );
add_action( 'edited_term', 'my_custom_flush_rewrite_rules', 10, 3 );
add_action( 'delete_term', 'my_custom_flush_rewrite_rules', 10, 3 );
function my_custom_flush_rewrite_rules( $term_id, $tt_id, $taxonomy ) {
$taxonomies_to_refresh = array( 'Speaker' );
if ( in_array( $taxonomy, $taxonomies_to_refresh ) ) {
flush_rewrite_rules();
}
}