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

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.

Leave a Comment