Add rewrite endpoint to author page + pagination

I want to add a new endpoint to the author page, so that the URL looks like this:

http://example.com/writer/username/articles

Read More

So far, I have:

  • Changed the author base
  • Added a rewrite rule
  • Setup the query_vars
  • Added the endpoint
  • Used template_redirect to use my template

Result: 404 Page Not Found (even after flushing the rewrite rules). I can’t figure out where the problem is. Also I’d like to add pagination to the endpoint. Below is my code:

Changed the author base:

function foo_change_author_base() {
    global $wp_rewrite;
    $wp_rewrite->author_base = 'writer';
}
add_filter( 'init', 'foo_change_author_base', 0 );

Added a rewrite rule:

function foo_rewrite_rule()
{
    add_rewrite_rule( 'writer/([^/]+)/articles(/(.*))?/?$', 'index.php?author_name=$matches[1]&articles=$matches[3]', 'top' );
}
add_action( 'init', 'foo_rewrite_rule' );

Setup query_vars:

function foo_add_vars($vars) {
    $vars[] = 'articles';   
    return $vars;
}
add_filter('query_vars', 'foo_add_vars');

Added the endpoint:

function foo_add_endpoint() {
    global $wp_rewrite;
    add_rewrite_endpoint( 'articles', EP_AUTHORS | EP_PAGES );
}
add_action( 'init', 'foo_add_endpoint');

And added my template:

function foo_rewrite_template()
{
    global $wp_query;

    if ( array_key_exists( 'articles', $wp_query->query_vars ) ) {
        include (get_template_directory_uri() . '/articles.php');
        exit;
    }
}
add_action( 'template_redirect', 'foo_rewrite_template' );

Related posts

2 comments

  1. Your code should works. The line:

    include (get_template_directory_uri() . '/articles.php');
    

    Needs to have allow_url_include=1 in the server configration because you are trying to include a file via http. Can you check this?

    You must know also that template_redirect should be use for a real redirect, a include() may have undesired effects here. I think what you really want is template_include:

    add_filter('template_include', 'my_template_include');
    
    function my_template_include( $template ) {
        global $wp->query;
        if ( array_key_exists( 'articles', $wp_query->query_vars ) ) {
            return get_template_directory() . '/articles.php';
        }
       return $template;
    }
    

    So here is my code:

    function foo_change_author_base() {
        global $wp_rewrite;
        $wp_rewrite->author_base = 'writer';
    }
    add_filter( 'init', 'foo_change_author_base', 0 );
    
    function foo_rewrite_rule()
    {
        add_rewrite_rule( 'writer/([^/]+)/articles/page/([0-9]{1,})/?$', 'index.php?author_name=$matches[1]&articles=1&paged=$matches[2]', 'top' );
        //If you don't want the last trailing slash change the las /?$ to just $
        add_rewrite_rule( 'writer/([^/]+)/articles/?$', 'index.php?author_name=$matches[1]&articles=1', 'top' );
    }
    add_action( 'init', 'foo_rewrite_rule' );
    
    function foo_add_vars($vars) {
        $vars[] = 'articles';   
        return $vars;
    }
    add_filter('query_vars', 'foo_add_vars');
    
    function foo_add_endpoint() {
        add_rewrite_endpoint( 'articles', EP_AUTHORS );
    }
    //add_action( 'init', 'foo_add_endpoint'); // Commented out
    // Edit: add_rewrite_endpoint is not needed when using add_rewrite_rule
    
    
    // auto-add the articles endpoint to author links
    function foo_author_link_filter( $link, $author_id, $author_nicename ) {
        return user_trailingslashit($link) . 'articles/';
    }
    add_filter( 'author_link', 'foo_author_link_filter', 20, 3);
    
    add_filter('template_include', 'foo_template_include');
    function foo_template_include( $template ) {
        global $wp_query;
        //You may need some other checks
        if ( array_key_exists( 'articles', $wp_query->query_vars ) ) {
            return get_template_directory() . '/articles.php';
        }
        return $template;
    }
    

    Now go to yoursite.com/writer/author_name/articles/

  2. First if you add the endpoint, you don’t need to add the rewrite rule. However if you want to handle the paging is better use the rewrite rule. Really 2 rewrite rules, on for pagen one for not paged.

    After that, your articles query var is not intended to contain nothing just ‘exist’ or not. For this reason you can just set it to 1 if it exists.

    Then just add a filter on template include, like @cybnet suggest in his answer.

    All code should be something like:

    function foo_change_author_base() {
        global $wp_rewrite;
        $wp_rewrite->author_base = 'writer';
    }
    add_filter( 'init', 'foo_change_author_base', 0 );
    
    function foo_add_vars($vars) {
        $vars[] = 'articles';   
        return $vars;
    }
    add_filter('query_vars', 'foo_add_vars');  
    
    function foo_rewrite_rule() {
        add_rewrite_rule( 'writer/([^/]+)/articles/page/([^/]*)$', 'index.php?author_name=$matches[1]&articles=1&paged=$matches[2]', 'top' );
        add_rewrite_rule( 'writer/([^/]+)/articles(.*)$', 'index.php?author_name=$matches[1]&articles=1', 'top' );
    }
    add_action( 'init', 'foo_rewrite_rule' );
    
    function foo_rewrite_template( $template ) {
        if ( ! is_author() ) return $template;
        global $wp_query;
        if ( $wp_query->get('articles') ) return ( get_template_directory(). '/articles.php');
        return $template;
    }
    add_filter( 'template_include', 'foo_rewrite_template' );
    
    // add a filter to author link, so 'get_author_posts_url' return the customized url
    function foo_author_link_filter( $link, $author_id, $author_nicename ) {
        return user_trailingslashit($link) . 'articles/';
    }
    add_filter( 'author_link', 'foo_author_link_filter', 20, 3);
    

    That will works good with pagination. Only remember to save the permalink settings again.


    Below a print-screen from my test environment where I test this code:

    enter image description here

Comments are closed.