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 4×4 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 4×4 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 4×4 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.

2 s
2

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
    }
}

Leave a Reply

Your email address will not be published. Required fields are marked *