In a simple WordPress plugin I have redirected commenter links to the URL /user/user_id
with the following code:
define('PROFILE', '<a href="/user/%d">%s</a>');
function my_get_comment_author_link($comment_ID) {
global $comment;
return sprintf(PROFILE, $comment->user_id,
$comment->comment_author);
}
add_action('get_comment_author_link',
'my_get_comment_author_link');
How could I please show a simple public user profile (for all registered users and not just authors) displaying the user name at that URL?
I guess I should create a PHP script in my child 2013 theme -
<?php
/* Template Name: Public User Profile */
?>
<?php get_header(); ?>
<?php
$my_query = new WP_Query($args);
// somehow get the user ID out of URL?
// somehow get the WP_User object?
printf('<p>Name: %s</p>', $user->display_name);
?>
<?php get_footer(); ?>
But how to make the WordPress to execute that PHP script, when the URL /user/user_id
is reuqested?
Should I use the Rewrite API here and how? I have tried the following, but don't see any effect:
add_rewrite_rule('/user/(\d+)',
'index.php?XXX=$matches[1]',
'top'
);
flush_rewrite_rules();
Or am I missing something, like maybe I should add a custom post type first? (As you see - I am confused and "lost in the docs").
UPDATE:
Can I maybe override the_content
hook - but how to detect that a /user/user_id
page has been called?
function my_content($content)
{
if (NOT /user/user_id CALLED)
return $content;
// otherwise somehow extract the user_id
// somehow get the corresponding WP_User
return sprintf('<p>Name: %s</p>', $user->display_name);
}
add_action('the_content', 'my_content');
Here are some (hopefully helpful) remarks:
Avoid putting everything into a giant super class, keep your classes as small and focused (task oriented) as possible. Auto loading classes can also be handy.
Keep your add_rewrite_rule
within the init
hook, because you don't want to loose the rewrite when you visit the permalink settings page and re-save the permalinks:
public static function init()
{
// ... your code ...
add_rewrite_rule(
'user/([^/]*)/?',
'index.php?wpcg_user=$matches[1]',
'top'
);
}
Notice the /?
part, to account for both user/123
and user/123/
. The add_rewrite_rule()
call will not flush the rewrite rules automatically.
Another way is to register an endpoint with add_rewrite_endpoint
:
public static function init()
{
// ... your code ...
add_rewrite_endpoint( 'user', EP_ALL );
}
where you can modify the places where it will be accessible: EP_ALL
, EP_PAGES
, EP_PERMALINK
, ...
. Notice that it will create a new rewrite rule where /user/123/
is mapped to ?user=123
.
You can use the template_redirect
action or template_include
filter to modify what template you want to display.
You should register your custom GET variable, wpcg_user
, with the query_vars
filter, for example:
public static function query_vars( $vars )
{
$vars[] = 'wpcg_user';
return $vars;
}
so you can retrieve it later with get_query_var( 'wpcg_user' )
.
When get_query_var( 'wpcg_user')
is non-empty, you know that the requested url is like http://example.com/user/123/
.
You should allow the WordPress admin to override the default plugin template, tpl-user.php
, by copying it into the current theme directory. The function locate_template
can help you with that:
if ( '' != locate_template( 'tpl-user.php') )
Your template_redirect
method, if you choose to use the corresponding hook, could then look like this:
public static function template_redirect()
{
$wpcg_user = get_query_var( 'wpcg_user' );
$tpl = 'tpl-user.php'; // Your custom template file.
if( ! empty( $wpcg_user ) )
{
if ( '' == locate_template( $tpl, TRUE ) )
include( plugin_dir_path( __FILE__ ) . $tpl );
exit();
}
}
where you might have to adjust the path to your tpl-user.php
template, for example if you keep it in a sub-directory within your wp-city-gender
plugin directory. Notice that we use the second input argument of the locate_template()
function, so it will load the template if it can find it.
Your tpl-user.php
template file could look like this:
<?php
/* Template Name: Public User Profile */
?>
<?php get_header(); ?>
<div>
<?php
// Get the user query:
$wpcg_user = get_query_var( 'wpcg_user' );
// Get corresponding user by id:
$user = get_user_by( 'id', absint( $wpcg_user ) );
if( $user ):
printf('<p> Name: %s </p>', $user->display_name );
printf('<p> City: %s </p>', get_user_meta( $user->ID, 'city', TRUE));
printf('<p> Gender: %s </p>', get_user_meta( $user->ID, 'gender', TRUE));
else:
_e( 'Sorry, no user found!' );
endif;
?>
</div>
<?php get_footer(); ?>
where we use the get_user_by()
function, to retrieve the corresponding user data.
We could easily have used the user slug instead of the user id, by using get_user_by( 'slug', $wpcg_user );
instead of get_user_by( 'id', absint( $wpcg_user ) );
.
You need the following, in your current setup:
add_action( 'template_redirect', array( CNAME, 'template_redirect') );
add_filter( 'query_vars', array( CNAME, 'query_vars') );
//add_action( 'template_include', array( CNAME, 'template_include') );
activate the corresponding hook callbacks.
There are many tools available to help you with custom rewrites, for example the Monkeyman Rewrite Analyzer. It has not been updated in a while, but still works great.
Here's a screenshot showing the /user/1/
inspection, with the above rewrite:
I hope this helps. Just let me know if you need help implementing this. I tested these modifications on my install and it worked there.
Update:
In response to a comment:
How to handle the case where the template is located in a sub-directory, for example /templates/profile.php
?
We can use the following:
if ( '' == locate_template( 'templates/profile.php', TRUE ) )
include( plugin_dir_path( __FILE__ ) . 'templates/profile.php' );
This means:
If /wp-content/themes/MYTHEME/templates/profile.php
is located, then it will be automatically loaded.
Else: /wp-content/plugins/wp-city-gender/templates/profile.php
is loaded.
where we assume that __FILE__
is in the wp-city-gender
root directory.
How about you check the page template instead of the url??
if ( is_page_template('public_profile.php') ) { // code to execute when the pages using the Template of public_profile.php file(Your Public User Profile Template file) are loaded. }
Have a look at this function is_page_template()
Or you can also get the template used by the current page to check the template. See get_page_template()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With