1

I don't want to use the category page as usual (list of posts). I would like to add more content: text, images, columns. Which is the best solution?

  • Maybe redirect from a category page to a page?
  • Or get the content of page and show it in the category page?

Thanks.

1
  • Rather than worry about re-directing, you can just create your own archive template and change it to be how you want it to be, assuming all your category archives are going to behave like that "page" you have in mind. If you want editable content on your archive, you can use your 2nd suggestion of just pulling that content into your template. codex.wordpress.org/Category_Templates Hope that helps!
    – RachieVee
    Nov 14, 2014 at 21:38

2 Answers 2

0

As said in one of the comments, this is really simple. Within your theme folder, you can create a file called category.php. Once in place, you can modify to your hearts content without the need to do anything fancy such as redirection. If you want to target a specific category, let's say music, then the file would be category-music.php

It's also worth noting, that if you're using a theme you did not develop, to create a child theme and put this file in that directory instead. You should never modify an existing themes files, including creating new files, because all your changes will be lost once you update the theme.

3
  • Thanks for your answer, but I want to edit the content: text, images... using the content editor. I don't want to modify my template files. Nov 18, 2014 at 12:19
  • So to clarify, you want it to act like a category page, listing the posts of that category, but you dont want to edit the template, and instead want to edit the page via the backend editor? Nov 19, 2014 at 17:18
  • Yes, that is the question. Nov 19, 2014 at 20:02
0

Edit: Fragging dammit, i wrote a wall of text AGAIN without checking when the question was asked. As this was 8 years ago, i'm pretty sure this won't help whoever asked the question originally. I will still post the answer for those who might end up here having the same question.


Okay, this is something that is asked by clients really often, and it can be solved various ways. The one i like to use is the "tie a custom post type to a category"-way. (You could also use pages for this, but this can get a bit messy).

Step 1: Register a custom post type, maybe "category-content".

// Register Custom Post Type
function register_category_content_post_type() {

    $labels = array(
        'name'                  => _x( 'Categories Content', 'Post Type General Name', 'text_domain' ),
        'singular_name'         => _x( 'Category Content', 'Post Type Singular Name', 'text_domain' ),
        'menu_name'             => __( 'Category Content', 'text_domain' ),
        'name_admin_bar'        => __( 'Category Content', 'text_domain' ),
        'archives'              => __( 'Category Content Archives', 'text_domain' ),
        'attributes'            => __( 'Category Content Attributes', 'text_domain' ),
        'parent_item_colon'     => __( 'Parent Category Content:', 'text_domain' ),
        'all_items'             => __( 'All Category Contents', 'text_domain' ),
        'add_new_item'          => __( 'Add Category Content', 'text_domain' ),
        'add_new'               => __( 'Add New', 'text_domain' ),
        'new_item'              => __( 'New Category Content', 'text_domain' ),
        'edit_item'             => __( 'Edit Category Content', 'text_domain' ),
        'update_item'           => __( 'Update Category Content', 'text_domain' ),
        'view_item'             => __( 'View Category Content', 'text_domain' ),
        'view_items'            => __( 'View Categories Content', 'text_domain' ),
        'search_items'          => __( 'Search Category Content', 'text_domain' ),
        'not_found'             => __( 'Not found', 'text_domain' ),
        'not_found_in_trash'    => __( 'Not found in Trash', 'text_domain' ),
        'featured_image'        => __( 'Featured Image', 'text_domain' ),
        'set_featured_image'    => __( 'Set featured image', 'text_domain' ),
        'remove_featured_image' => __( 'Remove featured image', 'text_domain' ),
        'use_featured_image'    => __( 'Use as featured image', 'text_domain' ),
        'insert_into_item'      => __( 'Insert into Category Content', 'text_domain' ),
        'uploaded_to_this_item' => __( 'Uploaded to this Category Content', 'text_domain' ),
        'items_list'            => __( 'Category Content list', 'text_domain' ),
        'items_list_navigation' => __( 'Category Content list navigation', 'text_domain' ),
        'filter_items_list'     => __( 'Filter Category Content list', 'text_domain' ),
    );
    $args = array(
        'label'                 => __( 'Category Content', 'text_domain' ),
        'description'           => __( 'The Content for Categories', 'text_domain' ),
        'labels'                => $labels,
        'supports'              => array( 'title', 'editor', 'revisions' ),
        'hierarchical'          => false,
        'public'                => true,
        'show_ui'               => true,
        'show_in_menu'          => 'edit.php',
        'menu_position'         => 5,
        'show_in_admin_bar'     => false,
        'show_in_nav_menus'     => false,
        'can_export'            => true,
        'has_archive'           => false,
        'exclude_from_search'   => true,
        'publicly_queryable'    => false,
        'rewrite'               => false,
        'capability_type'       => 'page',
        'show_in_rest'          => true,
    );
    register_post_type( 'category_content', $args );

}
add_action( 'init', 'register_category_content_post_type', 0 );

The Custom post type is registered to be non-viewable on its own in the frontend and is excluded from the search. That is so that the Posts can not be viewed "on their own". Also, the CPT will be positioned into the "Posts" Submenu in the backend.

Step 2: Register a metabox within the category edit screen to attach a "category content" post to a category. This can be done most easily with a plugin like cmb2, but for the sake of "doing this without plugins", we're gonna do it manually anyway.

function wpse_168452_add_category_fields() {
    $category_content_posts = get_posts(
        array(
            'post_type' => 'category_content',
            'posts_per_page' => -1,
            'orderby'   => 'post_title',
            'order' => 'ASC'
        )
    );
    if( $category_content_posts ){
        ?>
        <label for="content_post_for_this_category">Show the content of this Post on the Category Page</label>
        <select name="content_post_for_this_category" id="content_post_for_this_category">
            <option value="">Please choose a post for content</option>
            <?php 
            foreach( $category_content_posts as $category_content_post ){
                ?>
                <option value="<?php echo $category_content_post->ID; ?>">
                    <?php echo apply_filters( 'the_title', $category_content_post->post_title ); ?>
                </option>
                <?php
            }
            ?>
        </select>
        <?php
    }
}
add_action( 'category_add_form_fields', 'wpse_168452_add_category_fields' );
add_action( 'category_edit_form', 'wpse_168452_add_category_fields' );

function wpse_168452_save_category_content_fields( $term_id ) {
    if( ! isset( $_POST['content_post_for_this_category'] ) )
        return;

    if( empty( $_POST['content_post_for_this_category'] ) ){
        delete_term_meta( $term_id, '_category_content_id' );
        return;
    }

    $content_post_id = absint( $_POST['content_post_for_this_category'] );
    if( $content_post_id ){
        update_term_meta( $term_id, '_category_content_id', $content_post_id );
    }
}
add_action( 'created_category', 'wpse_168452_save_category_content_fields' );
add_action( 'edited_category', 'wpse_168452_save_category_content_fields' );

Now, we have a custom post type that can house the custom content, and we can "connect" a category to a post. Now, let's put the stuff together!

Create a "category.php" file within your theme folder. In the file, you copy the normal "loop" you created, for instance from index.php. I copied the most bare-bones one i could find: the underscores index.php:

<?php
/**
 * The main template file
 *
 * This is the most generic template file in a WordPress theme
 * and one of the two required files for a theme (the other being style.css).
 * It is used to display a page when nothing more specific matches a query.
 * E.g., it puts together the home page when no home.php file exists.
 *
 * @link https://developer.wordpress.org/themes/basics/template-hierarchy/
 *
 */

get_header();
?>
    <div id="primary" class="content-area">
        <main id="main" class="site-main">
            <?php
            if ( have_posts() ) {
                /* Start the Loop */
                while ( have_posts() ) {
                    the_post();
                    /*
                    * Include the Post-Type-specific template for the content.
                    * If you want to override this in a child theme, then include a file
                    * called content-___.php (where ___ is the Post Type name) and that will be used instead.
                    */
                    get_template_part( 'template-parts/content', get_post_type() );
                }
            } else {
                get_template_part( 'template-parts/content', 'none' );  
            }
            ?>
        </main><!-- #main -->
    </div><!-- #primary -->
<?php
get_footer();

Now, we edit the upper part to get our connected post and echo it:

<?php
$category_id = get_queried_object_id();
$connected_post_id = get_term_meta( $category_id, '_category_content_id', true );
if( $connected_post_id ){
    $connected_post = get_post( $connected_post_id );
    if( $connected_post && ( get_post_status( $connected_post_id ) == 'publish' ) ){
        ?>
        <article id="post-<?php echo $connected_post_id; ?>">
             <div class="entry-content">
                  <?php echo apply_filters( 'the_content', $connected_post->post_content ); ?>
             </div>
        </article>
        <?php
    }
} 
?>

Also, for better styling possibilities, we'll wrap the main loop into a div. The complete category.php should now look like this:

<?php
/**
 * The main template file
 *
 * This is the most generic template file in a WordPress theme
 * and one of the two required files for a theme (the other being style.css).
 * It is used to display a page when nothing more specific matches a query.
 * E.g., it puts together the home page when no home.php file exists.
 *
 * @link https://developer.wordpress.org/themes/basics/template-hierarchy/
 *
 */

get_header();
?>
    <div id="primary" class="content-area">
        <main id="main" class="site-main">
            <?php
            $category_id = get_queried_object_id();
            $connected_post_id = get_term_meta( $category_id, '_category_content_id', true );
            if( $connected_post_id ){
                $connected_post = get_post( $connected_post_id );
                if( $connected_post ){
                    ?>
                    <article id="post-<?php echo $connected_post_id; ?>">
                        <div class="entry-content">
                            <?php echo apply_filters( 'the_content', $connected_post->post_content ); ?>
                        </div>
                    </article>
                    <?php
                }
            } 
            ?>
            <div class="loop-wrapper">
                <?php
                if ( have_posts() ) {
                    /* Start the Loop */
                    while ( have_posts() ) {
                        the_post();
                        /*
                        * Include the Post-Type-specific template for the content.
                        * If you want to override this in a child theme, then include a file
                        * called content-___.php (where ___ is the Post Type name) and that will be used instead.
                        */
                        get_template_part( 'template-parts/content', get_post_type() );
                    }
                } else {
                    get_template_part( 'template-parts/content', 'none' );  
                }
                ?>
            </div>
        </main><!-- #main -->
    </div><!-- #primary -->
<?php
get_footer();

Aaand... you're done. Create a "Category Content"-Post, attach it to a category by choosing it on the edit-category screen, and done.

I did not test this specific code in this configuration, but it should work pretty good.

Happy Coding!

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.