0

It seems to be a common question as to how to override an auto-generated category page with a manually-created Page when both exist at the same location

for example, /xxxx/ and /yyyy/ and /zzzz/ are categories, but for one of them, you want to use a custom Page (while leaving the others alone). So you create a Page with the slug "xxxx", but Wordpress chooses to serve the category instead of your Page

I found a lot about this online however all the existing solutions only work with classic themes

this seems to be the most common solution:

function loadPageFirst() {
    // get the actual category
    $actualCategory = get_category( get_query_var('cat') );
    // get the page with the same slug
    $matchingPage = get_page_by_path( $actualCategory->slug );

    // If no match, load the normal listing template and exit (edit if you are using a custom listing template, eg. category.php)
    if (!$matchingPage) {
        include( get_template_directory() . '/archive.php');
        die();
    }

    // Make a new query with the page's ID and load the page template
    query_posts( 'page_id=' . $matchingPage->ID );
    include( get_template_directory() . '/page.php');
    die();
}
add_filter( 'category_template', 'loadPageFirst' );

but page.php and archive.php don't exist on block themes

attempting this code unmodified will result in a 5XX error

attempting to replace the reference to archive.php with a reference to the theme's templates/archive.html will result in the raw content of archive.html being returned, which renders as a blank page

I'm currently working around this by giving the Pages an alternate slug & utilizing Cloudflare invisible rewrites to send traffic to the alternate slug, so that the visitor never sees the alternate slug... but that's not an elegant solution.

2 Answers 2

0

In your scenario, where you want to override an auto-generated category page with a manually-created Page in WordPress, especially when using block themes, the challenge arises because block themes use a different file structure compared to classic themes. They rely on HTML templates and theme.json instead of the traditional PHP templates.

Here's a more elegant solution that's tailored for block themes:

Use WordPress Rewrite Rules: Instead of using Cloudflare invisible rewrites, you can utilize WordPress's built-in rewrite rules. This approach will internally redirect requests for the category URL to your custom page URL.

Template Redirect Hook: Use the template_redirect action hook to check if the requested URL is one of your categories that needs to be overridden. If it is, then redirect to the corresponding custom page.

Maintain Block Theme Compatibility: Since block themes don't use page.php or archive.php, you'll need to ensure that your redirect points to a URL rather than trying to include a specific template file.

Here's a basic implementation of this approach:

function wpb_redirect_category_to_page() {
    if (is_category('your-category-slug')) {
        $page = get_page_by_path('your-custom-page-slug');
        if ($page) {
            wp_redirect(get_permalink($page->ID));
            exit;
        }
    }
}
add_action('template_redirect', 'wpb_redirect_category_to_page');

Replace 'your-category-slug' with the slug of the category you want to override, and 'your-custom-page-slug' with the slug of the custom page you want to show instead.

This code checks if the current request is for a specific category, and if so, it redirects to the custom page you've created. This should work seamlessly with block themes as it doesn't rely on specific template files.

Remember to flush your rewrite rules after adding this code. You can do this by visiting the Settings > Permalinks page in your WordPress admin and clicking "Save Changes".

This approach maintains the integrity of your site's URL structure and is more in line with WordPress best practices, avoiding the need for external solutions like Cloudflare rewrites.

2
  • My goal is to to have the page slug match the category name so none of this really helps me. Using wp_redirect in this scenario creates an infinite loop. It would work if I gave the pages a different slug, as I did with my Cloudflare solution, but it would be inferior to that solution because it wouldn't be totally transparent to the visitor (they would see the alternate slug names in the URL bar, etc). The goal is for the visitor to not know that any redirection is happening. Commented Jan 31 at 3:04
  • I posted another answer below, check that. wordpress.stackexchange.com/a/422204/238918 Commented Jan 31 at 4:54
0

You can modify your WordPress behavior to display a page instead of showing the category archive. However, the function you've provided wpb_redirect_category_to_page uses a redirection approach, which means it sends the user from the category URL to the page URL. This is not displaying the page content on the category URL itself but rather redirecting to a different URL where the page is located.

If you want to show the page's content while still on the category URL (i.e., without redirection), you will need to modify the category template to include the page's content. Here's an approach you can use:

Identify or Create the Category Template: First, identify if your theme has a specific template for the category (like category-your-category-slug.php or category.php). If not, you can create one.

Modify the Template: In this template, you'll need to query for the page you want to display and then loop through to display its content.

Here's an example of how this can be done:

<?php
// File: category-your-category-slug.php

get_header();

if (is_category('your-category-slug')) {
    $page = get_page_by_path('your-custom-page-slug');
    if ($page) {
        echo apply_filters('the_content', $page->post_content);
    } else {
        // Fallback content or category loop
        while (have_posts()) : the_post();
            // Your normal category loop content here
        endwhile;
    }
} else {
    // Normal category loop for other categories
    while (have_posts()) : the_post();
        // Your normal category loop content here
    endwhile;
}

get_footer();
?>

In this approach, when a user visits the category 'your-category-slug', WordPress will use category-your-category-slug.php template. The template checks if the category is 'your-category-slug' and then fetches the content of 'your-custom-page-slug' and displays it. If the page is not found, or for other categories, it falls back to the normal category loop.

Remember to replace 'your-category-slug' and 'your-custom-page-slug' with the actual slugs of your category and page. This method ensures that the user stays on the category URL but sees the content of the specified page.

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.