How to create user personal pages with information from their meta profile fields?

First of all register the cpt. Probably if you don’t want add the UI for that post type you can set the show_ui to false.

$args = array(
  'label' => 'Members',
  'public' => true,
  'exclude_from_search' => true,
  'show_ui' => false,
  'show_in_nav_menus' => false,
  'show_in_menu' => false,
  'show_in_admin_bar' => false,
  'hierarchical' => false,
  'has_archive' => true,
  'publicly_queryable' => true,
  'rewrite' => true,
  'query_var' => 'member'
);
register_post_type( 'member', $args );

After that create a function that accept an user id and create the post content

function create_member_page( $user_id = '' ) {
  $user = new WP_User($user_id);
  if ( ! $user->ID ) return '';

  // check if the user whose profile is updating has already a post
  global $wpdb;
  $member_post_exists = $wpdb->get_var( $wpdb->prepare(
   "SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type="member" and post_status="publish"", $user->user_nicename
  ) );

  // you have a custom role for members?
  // you should, because if not all user will have a page, also admin, subscribers...
  // if ( ! in_array('member', $user->roles) ) return '';

  $user_info = array_map( function( $a ){ return $a[0]; }, get_user_meta( $user->ID ) );
  $title = $user_info['first_name'] . ' ' . $user_info['last_name'];
  // of course create the content as you want
  $content="This is the page for: ";
  $content .= $user_info['first_name'] . ' ' .$user_info['last_name'];
  $post = array(
    'post_title' => $title,
    'post_name' => $user->user_nicename,
    'post_content' => $content,
    'post_status' => 'publish',
    'post_type' => 'member'
  );
  if ( $member_post_exists ) {
    $post['ID'] = $member_post_exists;
    wp_update_post( $post );
  } else {
    wp_insert_post( $post );
  }
}

Now you have to run this function on every user creation / updating

add_action( 'personal_options_update', 'create_member_page' );
add_action( 'edit_user_profile_update', 'create_member_page' );

That’s all.

Now you can create your archive-member.php template to show all members, you can get them using WP_Query or get_posts.

And, you can create the template single-member.php to show the member profile, that’s a real page, not a virtual one, for this reason you can use all the WP function with it.

If you want a link to the member page, of course you can use get_permalink($postid); but this is not an intuitive way, you probably prefer to get link from an user id or name, so let’s create anothe function:

function member_permalink ( $user="" ) {
  if ( ! empty($user) ) {
    if ( is_numeric($user) ) { // user id
      $userObj = get_user($user);
    } else { // user nicename
      $userObj = -1;
    }
  } else {
     $userObj = wp_get_current_user();
     $name = isset($userObj->user_nicename) ? $userObj->user_nicename : '';
  }
  if ( ! isset($name) ) $name = $userObj == -1 ? $user : $userObj->user_nicename;
  global $wpdb;
  $id = $wpdb->get_var( $wpdb->prepare(
    "SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type="member" AND post_status="publish"",
    $name
  ) );
  return $id ? get_permalink($id) : '';
}

This function is flexible, you can use it like: member_permalink($user_id) also you can use it like member_permalink($user_nicename).

If the current logged user is a member, you can use the function like member_permalink() to retrive the url of the current logged-in member.

Note the code is untested, and written here, without syntax highlight, so there are chances for typos…


A side note

Some time ago an user asked if was better generate ‘staff’ content from pages (like present solution) or from user meta fields. In that occasion I opted for second option. That’s because your question is different (virtual pages vs real pages), however read that question / answer can be useful for you.. Find it here.

Leave a Comment