Create fake paged author pages when there are no posts
-
I have created a profile page for all users in our database with author.php, see an example on
https://internationaldownhillfederation.org/member/berry-plasman/
I am now developing a new website where I’m using query vars to create ‘fake’ sub-pages, such as
https://internationaldownhillfederation.org/member/berry-plasman/race-attendance/
(which races he/she attended)https://internationaldownhillfederation.org/member/berry-plasman/written/
which posts he/she wrote (what’s normally shown on an author page)https://internationaldownhillfederation.org/member/berry-plasman/mentioned/
to show in which posts he/she got mentioned
Note: links are not working on live site (except first one).
The last one is the one which is giving me issues. I used ACF to be able to tag users in a normal post. On /mentioned/ I query the posts in which he/she got mentioned. That is not a problem.
The problem lies in the fact that I need to paginate these ‘mentioned’ posts BUT since 99% of the users have not written any posts, a paged author page returns a 404 because there are no posts for that user and thus no page 2.
-
I tried working with pre_get_posts to override the query (and the authors), since an author page only shows posts from author X… but no luck…
I think if I can override the authors, it should be able to do, but this doesn’t work (yet) on an author page.
Did you create the rewrite rules for those pages (e.g.
member/berry-plasman/race-attendance/
)? Or is this the problem?How did you change the author archive slug
/author
to/member
?Can you show us what you have working so far
I’ve extended the author archive pages with extra pages on a website before. I’m not sure this is what you need, but here’s how I did it. Try putting the following in your (child) theme’s functions.php file:
function ap_author_pages_get_page_query_vars() { // Array with extra author archive page slugs return array( 'race-attendance', 'written', 'mentioned', ); } add_filter( 'query_vars', 'ap_author_pages_add_query_var' ); function ap_author_pages_add_query_var( $query_vars ) { // Add a new query var to the public query vars. $query_vars[] = 'author_page'; return $query_vars; } add_action( 'generate_rewrite_rules', 'ap_author_pages_generate_rewrite_rules' ); function ap_author_pages_generate_rewrite_rules( $wp_rewrite ) { // Get the new author pages rewrite rules. $rules = ap_author_pages_get_rewrite_rules(); if ( is_array( $wp_rewrite->rules ) && ! empty( $rules ) ) { // Add the author page rewrite rules. $wp_rewrite->rules = $rules + $wp_rewrite->rules; } } function ap_author_pages_get_rewrite_rules() { global $wp_rewrite; $author_permastruct = $wp_rewrite->get_author_permastruct(); if ( ! $author_permastruct ) { return array(); } $query_vars = ap_author_pages_get_page_query_vars(); $rewrite_rules = array(); foreach ( $query_vars as $query_var ) { // Get the author page query permastruct. $permastruct = "{$author_permastruct}/{$query_var}"; // Generate the rewrite rules for the new author page. $rules = $wp_rewrite->generate_rewrite_rules( $permastruct ); // Get the rewrite rules for the query var only. $rules = ap_author_pages_get_query_var_rewrite_rules( $rules, $query_var ); // Add the rewrite rules. $rewrite_rules = $rules + $rewrite_rules; } return $rewrite_rules; } function ap_author_pages_get_query_var_rewrite_rules( $rules, $query_var ) { global $wp_rewrite; // New author page rewrite rules. $query_var_rules = array(); // Default match for an author archive query. $author_match = $wp_rewrite->index . '?author_name=' . $wp_rewrite->preg_index( 1 ); foreach ( $rules as $rule => $match ) { // Check if the query var is in the rule if ( false === strpos( $rule, $query_var ) ) { continue; } // Check if the author match is in the match if ( false === strpos( $match, $author_match ) ) { continue; } // Add <code>author_page</code> query var to the match. $new_match = $author_match . "&author_page={$query_var}"; // Update the match for the rewrite rule. $query_var_rules[ $rule ] = str_replace( $author_match, $new_match, $match ); } return $query_var_rules; }
This will add those extra pages and pagination rules if needed. You’ll need to re-save your permalinks at wp-admin > Permalinks before you can visit the pages.
You can then update the query for these pages with the
pre_get_posts
action.Example:
add_action( 'pre_get_posts', 'ap_author_pages_query' ); function ap_author_pages_query( $query ) { // Do nothing with the query if: // It's a query in the wp-admin // it's not the main query for an author archive page if ( is_admin() || ! ( $query->is_main_query() && is_author() ) ) { return; } $author_page = $query->get( 'author_page' ); if ( ! $author_page ) { // Normal author archive page // page = /member/author-name } if ( 'race-attendance' === $author_page ) { // page = /member/author-name/race-attendance } if ( 'written' === $author_page ) { // page = /member/author-name/written } if ( 'mentioned' === $author_page ) { // page = /member/author-name/mentioned } }
I hope this gets you in the right direction.
btw:
consider creating a child theme instead of editing your theme directly – if you upgrade the theme all your modifications will be lost. Or create a plugin with the code above.Just a note that there are also plugins you can use to create a child theme:
https://www.ads-software.com/plugins/search/child+theme/@bdbrown thanks for the response, but my theme is 100% custom and not available anywhere else, so there’s no child theme.
@keesiemeijer thanks for the response.
I do want to mention I use Timber instead of plain PHP. Now in reply to your question.
I have made the website available @ https://new.internationaldownhillfederation.org.
The profile I am testing with is https://new.internationaldownhillfederation.org/member/emily-pross/.
As you can see all subpages work.That is not the issue, that all works. It is when a user has NOT written any posts and I want to ‘reach’ a paged (author) page.
Emily has not written any posts so a paged author page does not exist. That is what I want to ‘fake’.You can see it at my own profile: https://new.internationaldownhillfederation.org/member/berry-plasman/written/
Those are the posts written by me and the actual posts of an author page, with pagination.The author archive slug was changed as follows:
function change_author_permalinks() { global $wp_rewrite; $wp_rewrite->author_base = 'member'; $wp_rewrite->flush_rules(); } add_action( 'init', 'change_author_permalinks' );
These are my rewrite rules:
function idf_rewrite_profile_pages() { add_rewrite_rule( 'member/([a-z-]+)/([a-z-]+)/?$', 'index.php?author_name=$matches[1]&subpage=$matches[2]', 'top' ); add_rewrite_rule( 'member/([a-z-]+)/mentioned/page/([0-9]+)/?$', 'index.php?paged=$matches[2]&author_name=$matches[1]&subpage=mentioned', 'top' ); add_rewrite_rule( 'member/([a-z-]+)/written/page/([0-9]+)/?$', 'index.php?paged=$matches[2]&author_name=$matches[1]&subpage=written', 'top' ); } add_filter( 'init', 'idf_rewrite_profile_pages', 1, 3 );
This checks if a member is ‘tagged’ in any posts
$rows = $wpdb->get_results( $wpdb->prepare( " SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key LIKE %s AND meta_value = %s ", 'idf_tagged_riders_%_member', // meta_name: $ParentName_$RowNumber_$ChildName $user_id ) ); if ( $rows ) { $post_ids = array(); foreach ( $rows as $row ) { $post_ids[] = intval( $row->post_id ); } $ppp = 14; $pages = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; $offset = ( get_query_var( 'paged' ) ) ? (( get_query_var( 'paged' ) - 1 ) * $ppp ) : false; $mentioned_args = array( 'posts_per_page' => -1, 'post__in' => $post_ids, 'orderby' => 'date', 'order' => 'DESC', ); $context[ 'mentioned' ] = get_posts( $mentioned_args ); $amount_posts = count( $context[ 'mentioned' ] ); $amount_pages = intval( round( count( $context[ 'mentioned' ] ) / $ppp ) ); if ( $amount_pages > 1 ) { $context[ 'mentioned_paging' ] = true; $big = 999999999; $args = array( 'base' => str_replace( $big, '%#%', esc_url( get_pagenum_link( $big ) ) ), 'format' => '/page/%#%', 'total' => $amount_pages, 'current' => max( 1, get_query_var( 'paged' ) ), 'show_all' => false, 'end_size' => 3, 'mid_size' => 2, 'prev_next' => true, 'prev_text' => __( '« Previous' ), 'next_text' => __( 'Next »' ), 'type' => 'list', ); $context[ 'pagination' ] = sprintf( '<div class="paginator">%s</div>', paginate_links( $args ) ); } }
This is my pre get posts:
function alter_query_for_author_mentioned_subpages( $query ) { if ( ! is_admin() && $query->is_main_query() && is_author() && 'mentioned' == get_query_var( 'subpage' ) && false != get_query_var( 'paged' )) { $member_name = $query->query[ 'author_name' ]; $user_id = get_user_by( 'slug', $member_name )->ID; global $wpdb; $rows = $wpdb->get_results( $wpdb->prepare( " SELECT * FROM {$wpdb->prefix}postmeta WHERE meta_key LIKE %s AND meta_value = %s ", 'idf_tagged_riders_%_member', // meta_name: $ParentName_$RowNumber_$ChildName $user_id ) ); if ( $rows ) { $paged = ( get_query_var( 'paged' ) ) ? get_query_var( 'paged' ) : 1; // when var_dumped on /member/emily-pross/mentioned/page/2/, output shows correct page number $post_ids = array(); foreach ( $rows as $row ) { $post_ids[] = intval( $row->post_id ); } $authors = get_all_authors_ids(); $authors[] = $user_id; $query->set( 'author__in', $authors ); $query->set( 'post__in', $post_ids ); } } } add_action( 'pre_get_posts', 'alter_query_for_author_mentioned_subpages' );
Any thoughts ?
- This reply was modified 6 years, 11 months ago by Beee.
I notice now, the page becomes unavailable due to insufficient memory… but only on the /mentioned subpage (for Emily). Not on mine.
Hmmm…not sure where I was going with that child theme suggestion. Clearly not applicable to your post. Sorry about the sidetrack.
All good ??
Try adding the query var
subpage
to the public query variables.function idf_add_query_vars( $query_vars ) { $query_vars[] = 'subpage'; return $query_vars; } add_filter( 'query_vars', 'idf_add_query_vars' );
You can reset the
paged
query var in thepre_get_posts
action. Here is an example:function alter_query_for_author_mentioned_subpages( $query ) { if ( ! is_admin() && $query->is_main_query() && is_author() ) { $subpage = get_query_var( 'subpage' ); if ( ( 'mentioned' === $subpage ) && $query->is_paged() ) { // Reset query var paged $query->set( 'paged', '' ); } } } add_action( 'pre_get_posts', 'alter_query_for_author_mentioned_subpages' );
I’m not sure that’s what you want to do as you can now visit all paged pages (
/page/2
page/3
etc.).Query vars are already added, because it’s used for other things as well.
function add_vars( $vars ) { $vars[] = "continent"; $vars[] = "subpage"; $vars[] = "category"; $vars[] = "booking_id"; return $vars; } add_filter( 'query_vars', 'add_vars' );
For some more clarity I added the full files to pastebin:
author.php – https://pastebin.com/W65iML2X
pre-get-posts.php – https://pastebin.com/vvkPkEw7This is the relevant part of the rewrites (bit updated for usernames)
function idf_rewrite_profile_pages() { add_rewrite_rule( 'member/([a-zA-Z0-9_-]+)/([a-z-]+)/?$', 'index.php?author_name=$matches[1]&subpage=$matches[2]', 'top' ); add_rewrite_rule( 'member/([a-zA-Z0-9_-]+)/mentioned/page/([0-9]+)/?$', 'index.php?paged=$matches[2]&author_name=$matches[1]&subpage=mentioned', 'top' ); add_rewrite_rule( 'member/([a-zA-Z0-9_-]+)/written/page/([0-9]+)/?$', 'index.php?paged=$matches[2]&author_name=$matches[1]&subpage=written', 'top' ); } add_filter( 'init', 'idf_rewrite_profile_pages', 1, 3 );
I can already visit /page/2 if a user has written that amount of posts, which can be seen on my profile, see https://new.internationaldownhillfederation.org/member/berry-plasman/written/page/2/ but if I change written to mentioned it goes to my first mentioned page (I only have one), but in my opinion the paged doesn’t throw an error because I have written enough posts to be able to create paged pages.
So I think, if a user has not written enough posts to page an author archive page, it fails…
I am starting to think it is impossible.
I think the authors need to be added to the query, but I can’t seem to do that…
Well I can add them, but they’re not recognised (yet).
I have given up on it… it takes me too much time to achieve, so I built a different solution. I now show 3 teasers per row instead of 2 which saves a lot of space and I can now easily fit 50 on a page.
See https://new.internationaldownhillfederation.org/member/emily-pross/mentioned/
I am going to look into lazy loading on a later stage. The launch is more important ?? Over 1 year work in it… Thanks for your time @keesiemeijer
- The topic ‘Create fake paged author pages when there are no posts’ is closed to new replies.