Paginate WPQuery redirect to page 1 - php

In my Wordpress template, I'm making a WP query in order to list all cities in specific regions (custom post type).
In some cases, regions have more than 3000 cities so the Query is too heavy and runs out of memory.
Therefore I'm using the paginate_links function in order to paginate each list when there are more than 500 results.
It works fine but the paginate links are somehow redirected to the main page.
Examples :
http://www.example.fr/my-region/page/2
redirect to
http://www.example.fr/my-region so I can never access to the paginated pages.
Here is my code (partial).
Do you see what may cause this problem?
<?php
$paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1;
$posts = array(
'post_type' => 'commune',
'posts_per_page'=> 500,
'paged' => $paged,
'orderby' => 'title',
'order'=> 'ASC',
'meta_key' => 'region',
'meta_value' => $reg_region
);
$communes = new WP_Query($posts );
$nb_communes = $communes-> found_posts;
?>
<div class="col-8 main-content">
<?php while (have_posts()) : the_post(); ?>
<?php
echo "<ul class=\"list-group\">";
while ($communes->have_posts() ) { $communes->the_post();
?>
<li class="list-group-item"><?php echo(get_field("commune")); ?> (<?php echo(get_field("cp")); ?>) - <?php echo(get_field("civilite")); ?> <?php echo(get_field("prenom")); ?> <?php echo(get_field("nom")); ?> </li>
<?php
}
echo "</ul>";
?>
<?php endwhile; // end of the loop. ?>
<div class="pagination">
<?php
echo paginate_links( array(
'base' => str_replace( 999999999, '%#%', esc_url( get_pagenum_link( 999999999 ) ) ),
'total' => $communes->max_num_pages,
'current' => max( 1, get_query_var( 'paged' ) ),
'format' => '?paged=%#%',
'show_all' => false,
'type' => 'plain',
'end_size' => 500,
'mid_size' => 1,
'prev_next' => true,
'prev_text' => sprintf( '<i></i> %1$s', __( 'Précédent', 'text-domain' ) ),
'next_text' => sprintf( '%1$s <i></i>', __( 'Suivant', 'text-domain' ) ),
'add_args' => false,
'add_fragment' => '',
) );
?>
</div>
I do not know if it's related but in my functions.php file, I have this override so that my cystompost type skip the /$name_of_custom_post_type/ in URLs.
/**
* Remove the slug from published post permalinks. Only affect our custom post type, though.
*/
function gp_remove_cpt_slug( $post_link, $post, $leavename ) {
$custom_post_types = array('departement', 'region', 'commune');
if ( ! in_array( $post->post_type, $custom_post_types ) || 'publish' != $post->post_status ) {
return $post_link;
}
$post_link = str_replace( '/' . $post->post_type . '/', '/', $post_link );
return $post_link;
}
add_filter( 'post_type_link', 'gp_remove_cpt_slug', 10, 3 );
/**
* Have WordPress match postname to any of our public post types (post, page, race)
* All of our public post types can have /post-name/ as the slug, so they better be unique across all posts
* By default, core only accounts for posts and pages where the slug is /post-name/
*/
function gp_parse_request_trick( $query ) {
// Only noop the main query
if ( ! $query->is_main_query() )
return;
// Only noop our very specific rewrite rule match
if ( 2 != count( $query->query ) || ! isset( $query->query['page'] ) ) {
return;
}
// 'name' will be set if post permalinks are just post_name, otherwise the page rule will match
if ( ! empty( $query->query['name'] ) ) {
$query->set( 'post_type', array('post', 'departement', 'region', 'commune' ) );
}
}
add_action( 'pre_get_posts', 'gp_parse_request_trick' );

Related

Wordpress wp_query not showing some posts

I'm trying to get 5 posts of one category and paginate them, but my loop doesn't get some posts. In this case, I put 5 posts to retrieve but the loop only returns 2 and sometimes 3.
Finally, when I'm trying to use pagination it doesn't work.
Here is my code:
<?php
// Protect against arbitrary paged values
$paged = ( get_query_var( 'paged' ) ) ? absint( get_query_var( 'paged' ) ) : 1;
$args = array(
'category__in' => array( 11 ),
'category__not_in' => '',
'posts_per_page' => 5,
'post_type' => 'post',
'post_status'=>'publish',
'paged' => $paged,
);
$the_query = new WP_Query($args);
?>
<?php if ( $the_query->have_posts() ) : ?>
<?php while ( $the_query->have_posts() ) : $the_query->the_post();
$the_query->the_post();
// Post content goes here...
//
echo '
<h3 class="tituliNota">
<a href="'.get_permalink().'" class="noteTitle">
<b>'.the_title( ' ', ' ', false ).'</b></a></h3>';
get_the_category();
wp_reset_postdata();
endwhile; ?>
<div class="pagination">
<?php
echo paginate_links( array(
'format' => 'page/%#%',
'current' => $paged,
'total' => $the_query->max_num_pages,
'mid_size' => 5,
'prev_text' => __('« Prev Page'),
'next_text' => __('Next Page »')
) );
?>
</div>
The main query runs before the template is loaded, and WordPress decides what template to load based on the results of that query.
You say your default posts_per_page is set to 5, and there are 2 or 3 posts in that category, so as far as WordPress knows, there is no page 2. Your custom query that you run in the template with a different posts per page setting is unrelated to the main query.
The solution is to make adjustments to the main query before the template is loaded, via the pre_get_posts action. This would go in your theme's functions.php file
function category_posts_per_page( $query ) {
if ( !is_admin()
&& $query->is_category()
&& $query->is_main_query() ) {
$query->set( 'posts_per_page', 5 );
}
}
add_action( 'pre_get_posts', 'category_posts_per_page' );

Wordpress Custom Post type Category View with Pagination

I have a custom post type 'charters' and within my category.php page I have a loop pulling in 'charter' posts for the current category id. I have a custom pagination setup displaying page numbers when I click page 2 link, it goes to URL /page/2 which displays a 404 error. I can't figure out why I am getting the 404. If I adjust my posts per page the pagination updates and displays the correct number of pages but the links do not show up.
Category.php Code:
<?php $paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
$product_args = array(
'post_type' => 'charters',
'posts_per_page' => 10, //the same as the parse_query filter in our functions.php file
'paged' => $paged,
'page' => $paged,
'cat' => $cat
);
$product_query = new WP_Query( $product_args ); ?>
<?php if ( $product_query->have_posts() ) : ?>
<!-- the loop -->
<?php while ( $product_query->have_posts() ) : $product_query->the_post(); ?>
<article class="loop">
<h3><?php the_title(); ?></h3>
<div class="content">
<?php the_excerpt(); ?>
</div>
</article>
<?php endwhile; ?>
<!-- end of the loop -->
<!-- pagination here -->
<?php
if (function_exists( 'custom_pagination' )) :
custom_pagination( $product_query->max_num_pages,"",$paged );
endif;
?>
<?php wp_reset_postdata(); ?>
<?php else: ?>
<p><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p>
<?php endif; ?>
Functions.php Code:
function prefix_change_cpt_archive_per_page( $query ) {
//* for cpt or any post type main archive
if ( $query->is_main_query() && ! is_admin() && is_post_type_archive( 'product' ) ) {
$query->set( 'posts_per_page', '10' );
}
}
add_action( 'pre_get_posts', 'prefix_change_cpt_archive_per_page' );
function prefix_change_category_cpt_posts_per_page( $query ) {
if ( $query->is_main_query() && ! is_admin() && is_category( 'test-category' ) ) {
$query->set( 'post_type', array( 'product' ) );
$query->set( 'posts_per_page', '2' );
}
}
add_action( 'pre_get_posts', 'prefix_change_category_cpt_posts_per_page' );
function custom_pagination( $numpages = '', $pagerange = '', $paged='' ) {
if (empty($pagerange)) {
$pagerange = 2;
}
global $paged;
if (empty($paged)) {
$paged = 1;
}
if ($numpages == '') {
global $wp_query;
$numpages = $wp_query->max_num_pages;
if(!$numpages) {
$numpages = 1;
}
}
$pagination_args = array(
'base' => get_pagenum_link(1) . '%_%',
'format' => 'page/%#%',
'total' => $numpages,
'current' => $paged,
'show_all' => False,
'end_size' => 1,
'mid_size' => $pagerange,
'prev_next' => True,
'prev_text' => __('«'),
'next_text' => __('»'),
'type' => 'plain',
'add_args' => false,
'add_fragment' => ''
);
$paginate_links = paginate_links($pagination_args);
if ($paginate_links) {
echo "<nav class='custom-pagination'>";
echo "<span class='page-numbers page-num'>Page " . $paged . " of " . $numpages . "</span> ";
echo $paginate_links;
echo "</nav>";
}
My Permalink Settings are set to "Post Name" I have a feeling this has something to do with rewrites but I can not figure out how to get the page urls to work correctly. An example of my categories are as follows:
/category/long-beach/
/category/san-diego/
you should try this:
<?php
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'charters',
'cat'=> $cat,
'post_per_page'=> 6,
'paged' => $paged
);
$my_query = new WP_Query( $args );
if( $my_query->have_posts() ) {
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<p><?php the_title(); ?></p><?php
endwhile;
}
wp_reset_query();
?>
<?php echo pnavigation( $query ); ?>
then you need to add following code to function.php :
function pnavigation( $wp_query ) {
$big = 999999999; // need an unlikely integer
$pages = paginate_links( array(
'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ),
'format' => '?paged=%#%',
'current' => max( 1, get_query_var('paged') ),
'total' => $wp_query->max_num_pages,
'prev_next' => false,
'type' => 'array',
'prev_next' => TRUE,
'prev_text' => '←',
'next_text' => '→',
) );
if( is_array( $pages ) ) {
$paged = ( get_query_var('paged') == 0 ) ? 1 : get_query_var('paged');
echo '<ul class="pagination pagination-lg">';
foreach ( $pages as $page ) {
echo "<li>$page</li>";
}
echo '</ul>';
}
}
you need to just replace url (client-testimonials) with your url
function pagination_rewrite() {
add_rewrite_rule('client-testimonials/page/?([0-9]{1,})/?$', 'index.php?pagename=client-testimonials&paged=$matches[1]', 'top');
}
add_action('init', 'pagination_rewrite');
If you are using default pagination then please use below code.
<?php
$current_page = get_queried_object();
$paged = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
$args = array(
'post_type' => 'charters',
'paged' => $paged,
'cat'=> $cat);
$my_query = new WP_Query( $args );
if( $my_query->have_posts() ) {
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<p><?php the_title(); ?></p><?php
endwhile;
}
next_posts_link( 'Older Entries', $my_query->max_num_pages );
previous_posts_link( 'Newer Entries' );
wp_reset_query();
?>
Add below code in your function.php
function posts_on_categorypage( $query ) {
if ( $query->is_category()) {
$query->set( 'posts_per_page', '10' );
}
}
add_action( 'pre_get_posts', 'posts_on_categorypage' );
There was a couple of errors in my code. This is what I get for copy/pasting code and not going through it line by line. Thanks everyone who helped out, but I got this to work by changing:
Bad Code:
function prefix_change_category_cpt_posts_per_page( $query ) {
if ( $query->is_main_query() && ! is_admin() && is_category( 'test-category' ) ) {
$query->set( 'post_type', array( 'product' ) );
$query->set( 'posts_per_page', '2' );
}
}
Good Code:
function prefix_change_category_cpt_posts_per_page( $query ) {
if ( $query->is_main_query() && ! is_admin() && is_category( $cat ) ) {
$query->set( 'post_type', array( 'charters' ) );
$query->set( 'posts_per_page', '10' );
}
}

Wordpress Multiple Post Type Loop shows same results on every page

So I am using WordPress with an underscores theme. I used code from twenty fourteen's theme with pagination.
if ( ! function_exists( 'public_notices_paging_nav' ) ) :
function public_notices_paging_nav() {
global $wp_query, $wp_rewrite;
// Don't print empty markup if there's only one page.
if ( $wp_query->max_num_pages < 2 ) {
echo ("<h4 class='one-page-results'>End of Results</h4>");
return;
}
$paged = get_query_var( 'paged' ) ? intval( get_query_var( 'paged' ) ) : 1;
$pagenum_link = html_entity_decode( get_pagenum_link() );
$query_args = array();
$url_parts = explode( '?', $pagenum_link );
if ( isset( $url_parts[1] ) ) {
wp_parse_str( $url_parts[1], $query_args );
}
$pagenum_link = remove_query_arg( array_keys( $query_args ), $pagenum_link );
$pagenum_link = trailingslashit( $pagenum_link ) . '%_%';
$format = $wp_rewrite->using_index_permalinks() && ! strpos( $pagenum_link, 'index.php' ) ? 'index.php/' : '';
$format .= $wp_rewrite->using_permalinks() ? user_trailingslashit( $wp_rewrite->pagination_base . '/%#%', 'paged' ) : '?paged=%#%';
// Set up paginated links.
$links = paginate_links( array(
'base' => $pagenum_link,
'format' => $format,
'total' => $wp_query->max_num_pages,
'current' => $paged,
'mid_size' => 1,
'add_args' => array_map( 'urlencode', $query_args ),
'prev_text' => __( '← Previous', 'public_notices' ),
'next_text' => __( 'Next →', 'public_notices' ),
'type' => 'list',
) );
if ( $links ) :
?>
<nav class="navigation paging-navigation" role="navigation">
<h1 class="screen-reader-text"><?php _e( 'Posts navigation', 'public_notices' ); ?></h1>
<?php echo $links; ?>
</nav><!-- .navigation -->
<?php
endif;
}endif;
This worked great when I only had one post type, but now I've made a loop that displays two post types and it works. But on every page its the same group of posts.
<?php
$postLoop = array(
'post_type' => array('public_notice_post', 'post'),
'orderby' => 'date',
'order' => 'DESC'
);
$query = new WP_Query( $postLoop );
if ($query->have_posts()) :
while ($query->have_posts()) : $query->the_post();
get_template_part( 'template-parts/content', get_post_format() );
endwhile;
public_notices_paging_nav();
endif;
wp_reset_query(); ?>
Anything will help. I've tried a lot.
Maybe you got a loop with no "wp_reset_query()" and this may caused some bugs on other loop.. just look all your loop to be sure there noone without reset query.
On which kind of page you coded this loop ? This is a custom template or other ?
Sorry for my english, im french.
To fix the original problem of duplicated posts on every page all I had to do was write my code like this. HOWEVER I am still having an issue of page count, but that will addressed elsewhere.
<?php
$page = get_query_var( 'paged' ) ? get_query_var( 'paged' ) : 1;
$ppp = get_option( 'posts_per_page' );
if ( $page == 1 )
$offset = 6;
else
$offset = 6 + ( $page - 1 ) * $ppp;
?>
<?php
$postLoop = array(
'post_type' => array('public_notice_post', 'post'),
'orderby' => 'date',
'order' => 'DESC',
'paged' => $paged,
'posts_per_page'=> $ppp,
'offset' => $offset
);
$wp_query = new WP_Query( $postLoop );
if ($wp_query->have_posts()) :
while ($wp_query->have_posts()) : the_post();
get_template_part( 'template-parts/content', get_post_format() );
endwhile;
public_notices_paging_nav();
endif;
wp_reset_query(); ?>

wordpress add field for every custom type

I want to create a stock level field in WooCommerce Products for every Store custom post type.
I've already created the Store custom post type and added 3 stores to it. I want to automatically add a "stock level at store" field every time someone adds a Store so that I could check the stocks at store level.
I'm trying to put the custom field at the Products->Inventory-> right under the Stock Quantity.
I've tried this:
$post_type = 'store';
$tax = 'show-topic';
$inv_arg_terms = get_terms(array('orderby' => 'id', 'order' => 'ASC'));
if ($inv_arg_terms) {
$args = array(
'post_type' => $post_type,
'post_status' => 'publish',
'posts_per_page' => - 1,
'orderby' => 'title',
'order' => 'ASC'
); // END $args
$my_query = null;
$my_query = new WP_Query($args);
if ($my_query->have_posts()) {
while ($my_query->have_posts()) : $my_query->the_post();
add_action( 'woocommerce_product_options_inventory_product_data', 'wc_inventory_stock_product_field' );
function wc_inventory_stock_product_field() {
woocommerce_wp_text_input( array( 'id' => 'stock_level_' . the_title(), 'class' => 'short wc_input_stock', 'label' => __( 'Stock Level at ' . the_title(), 'woocommerce' ) . ' (' . get_woocommerce_currency_symbol() . ')' ) );
}
add_action( 'save_post', 'wc_cost_save_product' );
function wc_cost_save_product( $product_id ) {
// stop the quick edit interferring as this will stop it saving properly, when a user uses quick edit feature
if (wp_verify_nonce($_POST['_inline_edit'], 'inlineeditnonce'))
return;
// If this is a auto save do nothing, we only save when update button is clicked
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
if ( isset( $_POST['stock_level_' . the_title()] ) ) {
if ( is_numeric( $_POST['stock_level_' . the_title()] ) )
update_post_meta( $product_id, 'stock_level_' . the_title(), $_POST['cost_price'] );
} else delete_post_meta( $product_id, 'stock_level_' . the_title() );
}
endwhile;
} // END if have_posts loop
wp_reset_query();
} // END if $inv_arg_terms
and I got this:
Fatal error: Call to undefined function get_userdata() in
.../wp-includes/query.php on line 4758
Is what I'm thinking possible? How do I go about it?
Thanks, appreciate every help I could get.
Finally got it to work. Here's the code:
add_action( 'woocommerce_product_options_inventory_product_data', 'wc_stock_product_field' );
add_action( 'woocommerce_process_product_meta', 'wc_stock_save_product' );
function wc_stock_product_field() {
global $woocommerce, $post;
$post_type = 'store';
$args = array(
'post_type' => $post_type,
'post_status' => 'publish',
'posts_per_page' => - 1,
'orderby' => 'id',
'order' => 'ASC',
'caller_get_posts' => 1
); // END $args
$store_query = null;
$store_query = new WP_Query($args);
if ($store_query->have_posts()) {
while ($store_query->have_posts()) : $store_query->the_post();
woocommerce_wp_text_input(
array(
'id' => get_the_id() ,
'class' => 'short wc_input_stock',
'label' => __( 'Stock Level # ' . get_the_title(), 'woocommerce' ) ) );
endwhile;
} // END if have_posts loop
wp_reset_query();
}
function wc_stock_save_product( $product_id ) {
// stop the quick edit interferring as this will stop it saving properly, when a user uses quick edit feature
if (wp_verify_nonce($_POST['_inline_edit'], 'inlineeditnonce'))
return;
// If this is a auto save do nothing, we only save when update button is clicked
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
$post_type = 'store';
$args = array(
'post_type' => $post_type,
'post_status' => 'publish',
'posts_per_page' => - 1,
'orderby' => 'id',
'order' => 'ASC',
'caller_get_posts' => 1
); // END $args
$store_query = null;
$store_query = new WP_Query($args);
if ($store_query->have_posts()) {
while ($store_query->have_posts()) : $store_query->the_post();
if ( isset( $_POST[get_the_id()] ) ) {
if ( is_numeric( $_POST[get_the_id()] ) )
update_post_meta( $product_id, get_the_id(), $_POST[get_the_id()] );
} else delete_post_meta( $product_id, get_the_id() );
endwhile;
} // END if have_posts loop
wp_reset_query();
}

Custom taxonomy and custom post type with custom pagination 404 not found

My pagination is throwing a 404 error when the posts from General -> Reading are smaller than my custom number of posts on my custom taxonomy cities (custom post type city). From what I saw on SO this issue can be fixed usually by using a filter of pre_get_posts, but don't know how to apply it on my case.
I want to mention that in the taxonomy-cities.php I am getting posts of a category of a custom taxonomy of a custom post type.
taxonomy-cities.php
$cat_ID = get_query_var('cities');
$custom_id = get_term_by('slug', $cat_ID, 'cities');
add_filter('posts_orderby', 'edit_posts_orderby');
function edit_posts_orderby($orderby_statement) {
global $aPostsIDs;
$orderby_statement = 'FIELD(ID, '.implode(',',$_SESSION['saved_city_ids']).')';
return $orderby_statement;
}
$offset = ($paged - 1) * $num_city_guides_post;
$args['post_type'] = 'city';
$args['posts_per_page'] = $num_city_guides_post; // 5
$args['orderby'] = $orderby; // rand
$args['order'] = $order; // DESC
$args['paged'] = $paged; // 1
$args['tax_query'] = array(
array(
'taxonomy' => 'cities',
'field' => 'id',
'terms' => array($custom_id->term_id) // 3742
)
);
}
$wp_query = new WP_Query($args);
if ( $wp_query->have_posts() ) :
while ( $wp_query->have_posts() ) : $wp_query->the_post();
// some code here
endwhile;
else: echo 'No Posts';
endif;
wp_reset_postdata();
For archive-city.php I am using this filter in the functions.php and it works fine, but it doesn't get applied to the taxonomy-cities.php so I get 404:
function portfolio_posts_per_page_city( $query ) {
if (array_key_exists('post_type', $query->query_vars)) {
if ( $query->query_vars['post_type'] == 'city' )
$num_city_guides_post = get_option('num_city_post');
if( empty( $num_city_guides_post ) )
$num_city_guides_post = 9;
$query->query_vars['posts_per_page'] = $num_city_guides_post;
return $query;
}
}
if ( !is_admin() ) add_filter( 'pre_get_posts', 'portfolio_posts_per_page_city' );
This is an old question however i recently had the same issue. The following Snippet is in fact the contents of my taxonomy-template.php using the standard WP_Query, example here.
How to properly paginate custom post type taxonomy
The Query
Firstly because it's a taxonomy template, the first line declares $term allowing me to access the term array and therefore the taxonomy id, name url etc.
Secondly i'm setting the term id as a variable to be used in the tax_query parameter. This is used to query my custom post type videos and then get the taxonomy (category) for the loop, stored in $term_id.
The Fix
Because i'm looping through the posts and limiting the results, we effectively need to search for our remaining posts while excluding the previous results and results thereafter. What this means is quite simple:
You must make your custom post types searchable in order for pagination to work:
Important:
'exclude_from_search' => false,
Example taxonomy-template.php
<?php $term = get_term_by( 'slug', get_query_var( 'term' ), get_query_var( 'taxonomy' ) ); ?>
<?php
$term_id = $term->term_id;
$paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'videos',
'posts_per_page' => 4,
'paged' => $paged,
'tax_query' => array(
array(
'taxonomy' => $term->taxonomy,
'field' => 'term_id',
'terms' => $term_id
)
)
);
$the_query = new WP_Query( $args );
?>
<?php if ( $the_query->have_posts() ) : while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<!-- Loop -->
<?php endwhile; ?>
<?php if ($the_query->max_num_pages > 1) : ?>
<?php endif; ?>
<?php else: ?>
<!-- Nothing Found -->
<?php endif; ?>
Maybe u can solve this without filters.
It`s work for pagination my custom posts types
$paged = get_query_var('paged') ? get_query_var('paged') : 1;
$args = array( 'post_type' =>'cities', 'posts_per_page' => 0, 'paged' => $paged );
$query = query_posts( $args );
if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
//Do wordpress Loop
<?php endwhile; else: include( get_404_template() ); ?>
<?php endif; wp_reset_postdata(); ?>
I had the same problem with my custom post taxonomies pagination. Older posts page was coming with a 404 page not found. This issue is related to WP taxonomy slug so you have to rewrite rules for your custom post type taxonomies like this below:
function generate_taxonomy_rewrite_rules( $wp_rewrite ) {
$rules = array();
$post_types = get_post_types( array( 'public' => true, '_builtin' => false ), 'objects' );
$taxonomies = get_taxonomies( array( 'public' => true, '_builtin' => false ), 'objects' );
foreach ( $post_types as $post_type ) {
$post_type_name = $post_type->name;
$post_type_slug = $post_type->rewrite['slug'];
foreach ( $taxonomies as $taxonomy ) {
if ( $taxonomy->object_type[0] == $post_type_name ) {
$terms = get_categories( array( 'type' => $post_type_name, 'taxonomy' => $taxonomy->name, 'hide_empty' => 0 ) );
foreach ( $terms as $term ) {
$rules[$post_type_slug . '/' . $term->slug . '/?$'] = 'index.php?' . $term->taxonomy . '=' . $term->slug;
$rules[$post_type_slug . '/' . $term->slug . '/page/?([0-9]{1,})/?$'] = 'index.php?' . $term->taxonomy . '=' . $term->slug . '&paged=' . $wp_rewrite->preg_index( 1 );
}
}
}
}
$wp_rewrite->rules = $rules + $wp_rewrite->rules;
}
add_action('generate_rewrite_rules', 'generate_taxonomy_rewrite_rules');
This should work for all custom post type taxonomies and if you want to be more specific then you can try updating these two variables like this:
$post_types = get_post_types( array( 'name' => 'city', 'public' => true, '_builtin' => false ), 'objects' );
$taxonomies = get_taxonomies( array( 'name' => 'cities', 'public' => true, '_builtin' => false ), 'objects' );
Finally, just use your default query loop without passing any arguments. Pages will be generated based on General -> Reading.

Categories