0

I have a custom post named blog, I am using a page with url - slug blog, with custom template for displaying the blog arhive.

This is the query I am using in the template file:

global $wp_query;

        $wp_query = new WP_Query( array( 'post_type' => 'blog', /*'cat' => $cat_id, */'orderby' => 'date', 'posts_per_page' => 2, 'paged' => $paged ) );

        if ($wp_query -> have_posts()) {
            while ($wp_query -> have_posts()) { 
                $wp_query -> the_post();
                    echo '<div class="f4">';

                    echo '<div class = "left">';
                    echo '<a href = "'; the_permalink(); echo  '">';
                        echo '<div class = "image">';
                            the_post_thumbnail('home-thumbnail');
                        echo '</div>';
                    echo '</a>';
                echo '</div>';

                echo '<div class = "right">';
                    echo '<a href = "'; the_permalink(); echo  '">';
                        echo '<h3>'; the_title(); echo '</h3>';
                    echo '</a>';
                    echo '<div class = "post-date">Posted on: '; echo get_the_date(); echo '</div>';
                    the_excerpt();
                echo '</div>';
            
            echo '</div>';
            };
        };
        wp_reset_postdata();
        // wp_reset_query();
        
        ?>
    </div>

</div>

<?php echo '<div class = "wrap blog-pagination">';
            the_posts_pagination( array( 'mid_size'  => 2, 'screen_reader_text' => __( ' ', 'textdomain' ), 'prev_text' => __( '< PREVIOUS', 'textdomain' ),
            'next_text' => __( 'NEXT >', 'textdomain' ), ) );
        echo '</div>'; ?>

I am Using this script that generates the cpt - blog, and a default custom taxonomy for the blog.

<?php
/*
 Plugin Name: blog and taxonomy
 Plugin URI: http://www.yashar.site/
 Description: A sample plugin to register blog CPT and blog_cat custom taxonomy and add a default category.
 Version: 1.0
 Author: Yashar Hosseinpour
 Author URI: http://www.yashar.site/
 */

namespace My_Plugin;

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

class Blog
{
    /**
     * Instance of Blog
     * @access protected
     * @var object $instance The instance of Blog.
     */
    private static $instance = null;

    /**
     * Blog constructor.
     * This is a private constructor to be used in getInstance method to do things in a singleton way
     * It's a good idea to leave this constructor empty and make `init` method public to use it outside of the class, which is a good thing for Unit Testing
     * @access private
     */
    private function __construct()
    {
        $this->init();
    }

    /**
     * Initialize the plugin.
     * You can make it public and use it outside of the class
     * @access private
     * @return void
     */
    private function init()
    {
        // It's possible to use one method to cover these and hook it to `init`. I just like the way using single purpose OOP methods.
        // Note the priorities
        add_action('init', [$this, 'register_cpt'], 10);
        add_action('init', [$this, 'register_blog_cat_tax'], 11);
        add_action('init', [$this, 'insert_default_blog_cat_term' ], 12);

        // `save_post_{$post->post_type}` hook is used. Doc: https://developer.wordpress.org/reference/hooks/save_post_post-post_type/
        add_action( 'save_post_blog', [$this, 'set_default_blog_cat'], 99, 2 );
    }

    /**
     * Register `Blog` CPT and `blog_cat` taxonomy to it
     * This should be done after `init`
     * @access public
     * @wp-hook init
     * @return void
     */
    public function register_cpt()
    {
        $labels = array(
            'name' => 'Blogs',
            'singular_name' => 'Blog',
            'add_new' => 'Add New',
            'add_new_item' => 'Add New Blog',
            'edit_item' => 'Edit Blog',
            'new_item' => 'New Blog',
            'all_items' => 'All Blogs',
            'view_item' => 'View Blog',
            'search_items' => 'Search Blogs',
            'not_found' =>  'No Blogs found',
            'not_found_in_trash' => 'No Blogs found in Trash',
            'parent_item_colon' => '',
            'menu_name' => 'Blog'
        );
        $args = array(
            'public' => true,
            'show_in_menu' => true,
            'labels' => $labels,
            'supports' => array( 'title', 'editor', 'author', 'thumbnail', 'excerpt', 'comments' ),
            'taxonomies' => array('post_tag', 'blog_cat')
        );
        register_post_type('blog', $args);
    }

    /**
     * Register `blog_cat` taxonomy
     * This should be done after registering CPT
     * @access public
     * @wp-hook init
     * @return void
     */
    public function register_blog_cat_tax() {
        $labels = [
            'name'                      =>  'blog Categories',
            'singular_name'             =>  'blog Category',
            'all_items'                 =>  'All blog Categories',
            'edit_item'                 =>  'Edit Category',
            'view_item'                 =>  'View Category',
            'update_item'               =>  'Update Category',
            'add_new_item'              =>  'Add New Category',
            'new_item_name'             =>  'Category Name',
            'parent_item'               =>  'Parent Category',
            'parent_item_colon'         =>  'Parent Category:',
            'search_items'              =>  'Search blog Categories',
            'popular_items'             =>  'Popular Categories',
        ];
        register_taxonomy(
            'blog_cat',
            'blog',
            array(
                'labels' => $labels,
                'show_ui' => true,
                'show_tagcloud' => false,
                'hierarchical' => true
            )
        );
    }

    /**
     * Insert default blog_cat
     * `default_{$taxonomy}` option is used to make this term as default `blog_cat` term (non-removable)
     * @access public
     * @wp-hook init
     */
    public function insert_default_blog_cat_term()
    {
        // check if category(term) exists
        $cat_exists = term_exists('default_blog_cat', 'blog_cat');

        if ( !$cat_exists ) {
            // if term is not exist, insert it
            $new_cat = wp_insert_term(
                'Blog',
                'blog_cat',
                array(
                    'description'   =>  ' ',
                    'slug'          =>  'blog',
                )
            );
            // wp_insert_term returns an array on success so we need to get the term_id from it
            $default_cat_id = ($new_cat && is_array($new_cat)) ? $new_cat['term_id'] : false;
        } else {
            //if default category is already inserted, term_exists will return it's term_id
            $default_cat_id = $cat_exists;
        }

        // Setting default_{$taxonomy} option value as our default term_id to make them default and non-removable (like default uncategorized WP category)
        $stored_default_cat = get_option( 'default_blog_cat' );

        if ( empty( $stored_default_cat ) && $default_cat_id )
            update_option( 'default_blog_cat', $default_cat_id );
    }

    /**
     * Add an default `blog_cat` taxonomy term for `blog` CPT on save
     * If no `blog_cat` is selected, default blog_cat will be registered to the post
     * @access public
     * @wp-hook save_post_blog
     * @param integer $post_id
     * @param object $post
     */
    public function set_default_blog_cat($post_id, $post)
    {
        if ( 'publish' === $post->post_status ) {
            $blog_cats = wp_get_post_terms( $post_id, 'blog_cat' );
            $default_blog_cat = (int) get_option('default_blog_cat');

            if ( empty($blog_cats) ) {
                wp_set_object_terms( $post_id, $default_blog_cat, 'blog_cat' );
            }
        }
    }

    /**
     * Instance
     * Used to retrieve the instance of this class.
     * @access public
     * @return object $instance of the class
     */
    static public function getInstance() {
        if (self::$instance == NULL) {
            self::$instance = new self();
        }
        return self::$instance;
    }
}

// Run this
Blog::getInstance();

The problem is that the pagination links are not working. I mean the /blog/page/2/ just end up with the 404 page.

link structure is set to: /%category%/%postname%/ and have to stay this way.

1 Answer 1

1

You should not be using WP_Query in this context. WordPress has already queried the correct posts for that archive with the main query, and you only need to use the basic loop to display them:

if ( have_posts() ) {
    while ( have_posts() ) { 
        the_post();
        
        // Post markup here.
    };
};
4
  • I have to query the custom post type - blog, so I need to modify the query. Commented Mar 25, 2021 at 16:41
  • No you don’t. As I said, WordPress queries the correct posts automatically. You do not need to do this. In no documentation or decent tutorials are you ever told to do this. Commented Mar 25, 2021 at 16:42
  • The archive-blog.php does not get loaded, instead I use a regular page and assigned to it a custom template to query the blog posts. Commented Mar 25, 2021 at 17:05
  • The correct template would be is taxonomy-blog_cat.php Commented Mar 26, 2021 at 0:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.