Support » Fixing WordPress » Paging in wordpress themes

  • First of all I apologise if I appear grumpy but I am!

    Surely it cannot be this <censored> hard to get paging working as I need in WordPress. I suspect that my situation may be unusual.

    I have different category templates that show two, thee or four columns per page and I can choose between them using the Category Templates plug in which works very well.

    The problem comes when trying to add paging to my templates. When I click “Next” (next_posts_link()) I get a not found, which I can correct by setting the “Blog pages show at most” option. Unfortunately that only works for one of my templates.

    With a bit of digging I found I could add an action to modify the query so I have added the following in to my functions.inc

    add_action( 'pre_get_posts', 'modify_query' );
    function modify_query($query)
    {
    	global $prime_cols;
    
    	if (!$query->is_category()) {
    		return;
    	}
    
    	if ( method_exists( $query, 'is_main_query' ) ) {
    		if (!$query->is_main_query()) {
    			return;
    		}
    	} else {
    		global $wp_the_query;
    		if ($query !== $wp_the_query) {
    			return;
    		}
    	}
    
    	var_dump($prime_cols);
    
    	$query->set('posts_per_page', $prime_cols);
    
    }

    and I have added the following to my two column template

    global $prime_cols;
    $prime_cols = 2;

    The var_dump in the modify_query routine shows that the $prime_cols variable is indeed (int) 2 but the $query->set only seems to work if I hard code the value instead of using the variable.

    Where am I going wrong?

    I should add that this is being done using a custom query

    $cat = get_query_var('cat');
    		$category = get_category ($cat);
    		$page = (get_query_var('paged')) ? get_query_var('paged') : 1;
    		$temp = $wp_query;
    
    		//  Search
    		$wp_query = new WP_Query();
    		$wp_query->query('post_type=page&post_status=publish&category_name=' . $category->slug . '&showposts=2&posts_per_page=2' . '&paged=' . $page);

    And it doesn’t appear to be the first time it is getting in to the modify query. The fist time (a default call?) it is showing $prime_cols as being null and I suspect this is the only time it is setting the <censored> value.

Viewing 4 replies - 1 through 4 (of 4 total)
  • That’s because the $prime_cols in your theme template doesn’t exist when the pre_get_posts action is doing it’s thing.

    The var_dump shows it as an int(2), int(3) or int(4) depending on which template I am in and to me that would more than suggest that is does exist at that point.

    It also shows a NULL which is coming out previously (which may be where you were referring to)


    See the top left and bottom right of the image linked for what I mean

    What is the fix?

    So… I think it goes like this.

    Page one:
    Run a default query ($prime_cols = NULL) this returns a resultset as it is starting at 0
    Runs my custom query ($prime_cols = 2) as it is starting at 0, paging correctly set using variable

    Page Two:
    Run a default query ($prime_cols = NULL) this returns null / false as it is starting at 10 and only 3 items exist
    Shows 404
    Never runs custom query.

    I guess I need to over-ride the default query rather than running a custom one. Is this possible?

    I’m not sure that “default” is the right term

    OK, I have a solution of sorts. I’m not entirely happy with it but I’m on a deadline. I’ll take the time to share anyway.

    1. Hack the Category Templates plug in so it can identify the template it will use

    2. In pre_get_posts use this to override settings for the default query

    3. No more custom queries (I like this bit)

    So in the Category Templates plug in replace the cat_temp function with

    function cat_temp($template, $include = true) {
    	global $wp_query;
    	$post_obj = $wp_query->get_queried_object();
    
    	if (is_single()) {
    		$data = cat_temp_get_data();
    		$categories = get_the_category($post_obj->ID);
    	} else if (is_category()) {
    		$data = cat_temp_get_data(true);
    		$categories[0] = &get_category($post_obj->cat_ID);
    	}
    	$temp_data;
    
    	// Get templates for post categories
    	foreach((array)$categories as $category) {
    		if ($data[$category->term_id]['template'] != '0') {
    			$temp_data[$data[$category->term_id]['template']] = $data[$category->term_id]['priority']+($category->term_id/80000);
    		}
    	}
    
    	// Get templates for parent categories
    	foreach((array)$data as $key => $cat) {
    		if ($cat['all'] == "all" && $cat['template'] != "0") {
    			$id = (is_single()) ? (int)$cat['id'] : $key;
    			$descendants = get_term_children($id, 'category');
    			if ($descendants && in_category($descendants)) {
    				$temp_data[$cat['template']] = $cat['priority']+($cat['id']/80000);
    			}
    		}
    	}
    
    	//print_r($temp_data);
    
    	// Sort templates by priotiry, and return the one with the highest priority
    	if (is_array($temp_data)) {
    		asort($temp_data);
    		$template = array_shift(array_keys($temp_data));
    	}
    
    	// If currrent post has a template, use that one instead
    	if (is_single()) {
    		$overRule = cat_temp_post_template($post_obj->ID);
    		if ($overRule) $template = $overRule;
    	}
    
    	// Return template path
    	if (!empty($template)) {
    		if ($include) {
    			if (file_exists(TEMPLATEPATH.$template)) {
    				include(TEMPLATEPATH.$template);
    				exit;
    			}
    		} else {
    			return $template;
    		}
    	}
    }

    and use it in the pre_get_posts hook

    add_filter( 'pre_get_posts', 'modify_query' );
    function modify_query($query)
    {
    
    	if (!$query->is_category()) {
    		return;
    	}
    
            global $wp_the_query;
    	if ( method_exists( $query, 'is_main_query' ) ) {
    		if (!$query->is_main_query()) {
    			return;
    		}
    	} else {
    
    		if ($query !== $wp_the_query) {
    			return;
    		}
    	}
    
    	$category = $wp_query->get_queried_object();
    	$page = (get_query_var('paged')) ? get_query_var('paged') : 1;
    	$query->set('post_type', 'page');
    	$query->set('category_name', $category->slug);
    	$query->set('paged', $page);
    
    	$template = cat_temp("", false);
    	switch ($template) {
    		case '/two-col.php':
    			$query->set('posts_per_page', 2);
    			$query->set('showposts', 2);
    			break;
    		case '/three-col.php':
    			$query->set('posts_per_page', 3);
    			$query->set('showposts', 3);
    			break;
    		case '/four-col.php':
    			$query->set('posts_per_page', 4);
    			$query->set('showposts', 4);
    			break;
    	}
    }

    If experienced WordPress developers don’t cough up their spines in this thread, I’ll send the Category Template changes upstream…

Viewing 4 replies - 1 through 4 (of 4 total)
  • The topic ‘Paging in wordpress themes’ is closed to new replies.