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

I asked here how to create virtual pages with information from the user meta profile fields using an external class. I got a good answer and also I have implemented it successfully (thanks to @g-m!). At the same time, the author of answer suggested me that what I want can be done “in a lot simpler and more performant way“, using the core WP functions, just creating a real post type: registering a CPT, maybe not public (so no UI is showed on dashboard), and on user profile saving/updating just created/updated CPT entry.

This is how I created and saved initially some extra user profile fields:

Read More
/* Add Extra Fields to the User Profile */
add_action( 'show_user_profile', 'extra_user_profile_fields' );
add_action( 'edit_user_profile', 'extra_user_profile_fields' );

function extra_user_profile_fields( $user ) { ?>
   <h3><?php _e("Academic", "blank"); ?></h3>
   <table class="form-table">
      <!-- Teaching position -->
      <tr>
      <th><label for="teaching_position"><?php _e("Teaching position"); ?></label></th>
      <td>
      <input type="text" name="teaching_position" id="teaching_position" value="<?php echo esc_attr( get_the_author_meta( 'teaching_position', $user->ID ) ); ?>" class="regular-text" /><br />
      <span class="description"><?php _e("Put here your teaching position"); ?></span>
      </td>
      </tr>
   </table>
}

/* Save Extra User Profile Fields */
add_action( 'personal_options_update', 'save_extra_user_profile_fields' );
add_action( 'edit_user_profile_update', 'save_extra_user_profile_fields' );

function save_extra_user_profile_fields( $user_id ) {
   if ( !current_user_can( 'edit_user', $user_id ) ) { return false; }
   update_user_meta( $user_id, 'teaching_position', $_POST['teaching_position'] );
}

What I want, is to put on my site a list of department members with links to their personal pages (e.g. example.com/users/user_nicename) with some content from their profiles. Pages must be created automatically, so I do not have to create manually a personal page for each new member. How can this be achieved (except the cited solution)?

Related posts

1 comment

  1. 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.

Comments are closed.