How to create a template for a custom URI associated with the user

I am working on a site where I am using a plugin called Favorite Posts so logged-in users can add a post (a custom post type) to their favorites.

I created a page called my-favorites which allows the logged-in user to see the posts he has favorited.

Read More

Now I need to create a page which allows the another user or visitor to check this user’s favorites.

So I need to be able to do three things:

  1. Get a function related to author that returns a link like
    example.com/user/username which I can append to /favorites to get
    the link – example.com/user/username/favorites (the_author_link() and get_the_author() link seems to link to the website and the_author_posts_url() outputs the a tag with the name. any function to just get the url or maybe modify author to show user instead?)

  2. Get WordPress to use a template called favorites.php to display this
    page. (If the structure matches, then how do I tell WordPress which template to use?)

  3. Get the user id of the user in order to show his/her favorites to
    the visitor. Right now, I use the [favorite-post] shortcode in my
    template file and can pass a parameter called

    [favorite-post user_id = ""]
    

    Will it automatically get the user id if the page is branched out from /author?

I found this article but it still deals with custom post types and query_vars which I am not using. How do I make it work for the favorites page? Most other similar questions asked here were solved using a slug for the custom post type or taxonomy.

Related posts

1 comment

  1. First of all, you ned a function (template tag) to display the url. You can write a custom function that output the url in the format you want, however, putting the username in a public url can be a security issue.

    The function can handle the link and accept an argument $user that can be a user id or a user object. If non is passed, the function will try to use current post author (if in the loop).

    function get_user_favorites_url( $user = NULL ) {
      if ( is_int($user) ) $user = new WP_User( $user );
      if ( ! $user instanceof WP_User ) $user = get_the_author();
      if ( $user instanceof WP_User && $user->exists() ) {
        return home_url( 'user/' . $user->user_login . '/favorites' );
      }
    }
    

    Now you have to make WordPress understand this kind of urls. You have to use a rewrite rule for the purpose.

    You said in OP that you are not using query vars, but you should. The problem is that once you want to use a pretty permalink, you have to use a rewrite rule, and any parameter added via a rewrite rule is only accessible via query var and not via $_GET.

    So:

    function user_favorites_rule() {
        add_rewrite_rule( 'user/([^/]+)/favorites', 'index.php?favorites=$matches[1]', 'top' );
    }
    add_action( 'init', 'user_favorites_rule', 1 );
    
    function user_favorites_var( $vars ) {
        $vars[] = 'favorites';
        return $vars;
    }
    add_filter( 'query_vars', 'user_favorites_var' );
    

    After adding this code, go in your backend, visit the page “Settings -> Permalinks” to flush rewite rules.

    Now you have an url format, and when you visit that url WordPress will set a query variable ‘favorites’ filling it with the required username.

    However, we wont WordPress load the ‘favorites’ page when we call that url.

    What I suggest you is to create a custom page template, and assign the page “My favorites” to it.

    So create a new php file, name it 'page-favorites.php', and inside it write only this:

    <?php
    /*
    Template Name: My Favorites
    */
    require( 'favorites.php' );
    

    Nothing else.

    Now, in the backend, create a page (if you don’t have it already), and assign to it the template just created.

    After that, we can use ‘pre_get_posts’ to query this page when the user favorites url is used.

    function user_favorites_noquery( $query ) {
      if ( is_admin() || ! $query->is_main_query() || ! $query->is_home() ) return;
      $user = $query->get('favorites');
      if ( ! empty($user) ) {
        $mq = array(
          'meta_key' => '_wp_page_template', 'meta_value' => 'page-favorites.php'
        );
        $query->set( 'post_type', 'page' );
        $query->set( 'meta_query', array($mq) );           
        $query->set( 'posts_per_page', 1);
        $query->query['favorites'] = NULL;
        $query->query_vars['favorites'] = NULL;
        user_favorites_get_user( $user );
        add_filter( 'template_include', 'user_favorites_template', 9999 );
        // following line is to prevent WordPress redirect to the page standard url
        remove_filter('template_redirect', 'redirect_canonical');
      }
    }
    add_action( 'pre_get_posts', 'user_favorites_noquery' );
    
    function user_favorites_get_user( $user = NULL ) {
      static $the_user = NULL;
      if ( ! empty($user)  ) $the_user = $user;
      return $the_user;
    }
    
    function user_favorites_template() {
      return get_template_directory() . '/favorites.php';
    }
    

    With this code, we tell WordPress to call first page with the template 'page-favorites.php' when the favorites url is required.

    The function user_favorites_get_user is an helper function we use to save the required user, avoiding the use of global variables.

    The function user_favorites_template force WordPress to load ‘favorites.php’ as template.

    Inside 'favorites.php' the relevant part is to output the shorcode for user favorites posts.

    There are 2 possibilities: an user is logged and want to see own favorites posts, or someone (logged in or not) want to see the posts favorited by an user.

    That can be translated in code like this:

    //favorites.php
    
    $user_required = user_favorites_get_user();
    $user = FALSE;
    if ( ! empty($user_required ) ) {
      $user = get_user_by( 'login', $user_required );
    } elseif ( is_user_logged_in() ) {
      $user = wp_get_current_user();
    }
    if ( $user instanceof WP_User && $user->exists() ) {
      echo do_shortcode( '[favorite-post user_id = "' . $user->ID . '"]' );
    } else {
      echo 'No user selected.';
    }
    

    Now, when a user is logged in, he/she can visit the url example.com/my-favorites (if ‘my-favorites’ is the slug of the page assigned to “My Favorites” page template) to see his/her own posts.

    Any logged or not logged visitor, can use an url like example.com/user/username/favorites and vieving the favorites post for that specific user.

Comments are closed.