6

First of all, I tried searching and working on this, but couldn't create the logic or method to do this.

I'm trying to display users and custom post type content together into a single loop. I can get the value of custom post type using WP_Query and users using WP_USER_Query. and I can display them simultaneously. But then the posts and users won't be mixed in the order of date.

I'm not sure if I can achieve this via custom query. My knowledge and experience is limited on this part.

Can anyone help me put in the right direction about how I can achieve this?


// Edit and Update

Thank you all for your comment, I believe I gave the half of the idea of what I really need and how I'm trying to achieve it. So I'll begin with the idea/scenario.

General Idea:

  1. I have Custom post type, let's call it "assignment" and "projects".
  2. I have users on the site, let's call them "teacher" and "student".
  3. multiple teachers can assign "assignment" and "projects" to multiple students.
  4. Now, I have a "Directory" page, on which I wish to display all (teacher, student, assignments, and projects).
  5. On the frontend, I wish to display each cpt entry and users in thumbnail view like the 4x4 grid.

Now, I have create a page-template called directory.php and used the following loop to display only cpt assignment and projects.

$args = array(
    'post_type' => array('assigment', 'project'),
    'post_status' => 'publish',
    'order' => 'ASC'
);

$query = new WP_query( $args );

and looped it like this

<?php if ( $query->have_posts() ) : ?>

    <?php
    while ( $query->have_posts() ) :
        $query->the_post();

        get_template_part( 'template-parts/content', get_post_type() );

    endwhile;

    the_posts_navigation();

else :

    get_template_part( 'template-parts/content', 'none' );

endif;
wp_reset_postdata();
?>

the code is working, but please focus on the syntax error if any. now the part of users. I wrote it like this.

$user = new WP_User_Query(array('role'=> 'teacher'));

if (!empty($user)) {
    foreach ($user as $teacher) {
        echo $teacher->first_name;
    }
}

you get the basic idea of how I can use the users.

The main Question

How can I merge Users within the post loop, so users and posts display in a grid of 4x4 and order by timestamps?

For example, we have the following with the date of creation.

Teach A ( 10 Jun, 2018 ) Teach B ( 12 Jun, 2018 ) Stud C ( 15 Jun, 2018 ) Assign 1 ( 16 Jun, 2018 ) Assign 2 ( 18 Jun, 2018 ) Stud D ( 20 Jun, 2018 ) Proj 1 ( 22 Jun, 2018 )

and then I display in the 4x4 grid like this.

Teach A Teach B Stud C Assign 1 Assign 2 Stud D Proj 1

Please let me know if it's still confusing.

  • I remember reading somewhere that there is no good reason for using a single loop. Perhaps you could add some context by explaining how exactly you want to display them(what order), and maybe it can be broken down into two loops or more. – D. Dan Jun 28 '18 at 12:48
  • can you please share your code – Dharmishtha Patel Jun 28 '18 at 13:01
  • What exactly are you trying to achieve? Maybe show us your code and give some example what you would like to get... It's a little bit hard to understand how these two loops should get merged... – Krzysiek Dróżdż Jun 28 '18 at 13:01
  • 1
    If you're doing this to try essentially display a list of 'events', like "X post was posted" and "Y user registered", you'd be better of creating a separate post type and creating new posts when these things occur, then looping through those. – Jacob Peattie Jun 28 '18 at 13:42
  • @JacobPeattie, not quite what you mentioned but I updated my question, would you please have a look at it? – Dilip Gupta Jun 29 '18 at 14:22
4
+50

You can not merge two different queries when the returned type is an object, because they have different methods and properties. Instead, you can get them as an array. Then you can merge them and compare the dates. For this, I'm going to use get_posts() over WP_Query(), and get_users() over WP_User_Query() to achieve this.

The code itself should be self explanatory.

// Get a list of users
$users = get_users ();

// Get an array of posts. Don't forget to set the args
$posts = get_posts();

// Let's merge these two
$users_posts = array_merge( $users, $posts );

// Now, let's sort both of them based on 
// their dates. a user object holds the date
// as `user_registered`, while a post object
// holds the date as `post_date`. We use the
// usort() function to do so.
usort( $users_posts, "sort_users_and_posts" );

// Function to sort the array
function sort_users_and_posts( $a, $b ){

    // Here's the tricky part. We need to get the
    // date based on the object type, and then compare them.

    // Get the date for first element
    if( $a instanceof WP_User ){
        $first_element_date = strtotime ( $a->user_registered );
    } else {
        $first_element_date = strtotime ( $a->post_date );
    }

    // Get the date for second element
    if( $b instanceof WP_User ){
        $second_element_date = strtotime ( $b->user_registered );
    } else {
        $second_element_date = strtotime ( $b->post_date );
    }

    // Now let's compare the dates

    // If the dates are the same
    if ( $first_element_date == $second_element_date ) return 0;

    // If one is bigger than the other
    return ( $first_element_date < $second_element_date ) ? -1 : 1;

}

// Now, we run a foreach loop and output the date.
// We need to check again whether the object is an
// instance of WP_Post or WP_User
foreach ( $users_posts as $object ) {
    if( $object instanceof WP_Post ){
        // This is a post
    } else {
        // This is a user
    }
}
  • I had thought about doing this, but pagination and scaling it up to hundreds of posts and users is going to be tricky. – Milo Jul 2 '18 at 17:24
  • @Milo That's gonna be tough, these are two different types of queries. But I couldn't think of a solution based natively on wp_query() , especially since I had this very same challenge before. Hopefully OP just wants a 4x4 grid. However I believe the pagination can be done via a custom rewrite rule. – Jack Johansson Jul 2 '18 at 19:00
  • Thanks, @JackJohansson, Your solution is best, I can get both values and loop it. – Dilip Gupta Jul 6 '18 at 9:00
3

You can create additional two custom post types teacher and student which will inherit from your WordPress user.

          +------+
     +----+ User +----+
     |    +------+    |
     |                |
     |                |
     v                v
+----+----+      +----+----+      +---------+      +------------+
| Teacher |      | Student |      | Project |      | Assignment |
+---------+      +---------+      +---------+      +------------+

You can relate WordPress user with teacher/student post type using post meta fields.

This data structure will allow you to create a single loop for all of your resources.

$args = array(
    'post_type' => array( 'teacher', 'student', 'assigment', 'project' ),
    'order' => 'ASC'
);

$query = new WP_query( $args );
  • Thanks, @motivast, But I can't use the users as cpt, because I have other features associated with Users. – Dilip Gupta Jul 6 '18 at 9:01
  • Sure, thats why you have to relate CPT with user. Also, you can use CPT only in your query, other features do not need to be related with. – kierzniak Jul 6 '18 at 9:05
  • Actually, I already tried this way and dropped the idea. Your solution works as a workaround method. but it's not for me and my query. Again, Thank you for taking your time on this question. – Dilip Gupta Jul 6 '18 at 9:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.