I have a website that lists businesses in different cities (this is a niche site, so all businesses have the same “classification”).
For starters I created a CPT for locations and a taxonomy called “Cities,” which 150 or so cities as terms.
All 300+ locations have been tagged with a city.
I was able to modify the CPT links so that they appear like so:
example.com/cityname/business-name
What I’d love to have (and not been able to accomplish yet) are urls like
example.com/cityname which would list all businesses from that city.
My understanding is that by default WP attempts to find a page with “cityname” as the name.
What would be the easiest way to reroute this request to use a taxonomy template? Or as an alternative, what would the easiest way be to have the page template detect the city name and pull posts tagged with that taxonomy term?
I suppose I could create rewrite rules in htaccess for all cities, but I’d prefer where the redirects were automatically added when a new city name is added to the taxonomy.
1 Answer
Here is some code that should do the trick:
//Creates special permastruct that turns all terms of cities into slugs
add_action( 'init', 'set_rewrite' );
function set_rewrite() {
//Get terms
$terms = get_terms( 'cities', array( 'hide_empty' => false ) );
//return if no terms
if( count( $terms ) < 1 ) return;
$slugs = wp_list_pluck( $terms, 'slug' );
//create term regex
$termregex = '(' . implode( '|', $slugs) . ')';
//New query var
add_rewrite_tag( '%cityname%', $termregex );
//Add permastruct
add_permastruct( 'cities_struct', '%cityname%/' );
//refresh if new term added
if( get_option( 'update_cities_struct' ) ) {
global $wp_rewrite;
$wp_rewrite -> flush_rules();
update_option( 'update_cities_struct', 0 );
}
}
//action to refresh rewrite rules when a new term is saved
add_action( 'created_cities', 'refresh_cities' );
add_action( 'edited_cities', 'refresh_cities' );
add_action( 'delete_cities', 'refresh_cities' );
function refresh_cities() {
update_option( 'update_cities_struct', 1 );
}
//set city name to the taxonomy cities
add_filter( 'parse_query', 'parse_cities_query' );
function parse_cities_query( $query ) {
if( !empty( $query->query_vars['cityname'] ) ) $query->set( 'cities', $query->query_vars['cityname'] )
}
Basically this creates a special permastruct that uses the slugs of the taxonomy cities
as its base. It creates a query variable called cityname
, which only accepts the slugs of the taxonomy and then sends the result to the proper taxonomy query variable.