0

I want to load 3 posts that have the same custom field value as the current post.
for example:
The current post has 3 custom fields:
color: black
background: red
lastname: doe
Now I want to load three posts with these custom fields:
first post: color:black
second post: background:red
third post: lastname:doe
these are my codes:

$page_id = get_the_ID();
$color= get_field( "color", $page_id );
$background= get_field( "background", $page_id );
$lastname= get_field( "lastname", $page_id );
$color_array = array ("the_color"=>$color);
$background_array = array ("the_background"=>$background);
$lastname_array = array ("the_lastname"=>$lastname);
$related_args = array($color_array ,$background_array ,$lastname_array );
foreach($related_args as $args) {
 foreach($args as $key => $value){
   echo $value; //to know the post after it are from that custom post
   $myargs = array(
            'post_type' => 'myposttype',
            'orderby'   => 'rand',
            'meta_key'      => $key,
            'meta_value'    => $value,
            'posts_per_page' => 1,
            );
         
        $the_query = new WP_Query( $myargs );
        if ( $the_query->have_posts() ) {
        $string .= '<ul>';
            while ( $the_query->have_posts() ) {
                $the_query->the_post();
                $string .= '<li><a href="'. get_permalink() .'">'. '<div class="post-image">' . get_the_post_thumbnail() . '</div>' . '<div class="post-title">' . get_the_title() . '</div>' .'</a></li>';
            }
            $string .= '</ul>';
            wp_reset_postdata();
        } else {
         
        $string .= 'no posts found';
        }
        echo $string;
  }
}

as you can see in codes, I've retrieved the current post custom fields value then I've created arrays that have the meta_key and meta_value. then created an array of that arrays. then I've created two loops to find 3 posts that each one of them has the same custom field as the current post.
The Problem:
It loads one post with the first custom field, two posts with the second custom field, and three posts with the third custom field.
But I want it to load one post with the first custom field, one post with the second custom field, one post with the third custom field.
Please tell me how can I achieve this.
Thanks

3
  • I think there is code missing here to cause what you're saying is happening. Can you supply more of your code/logic, please?
    – Paul G.
    Jun 13 '21 at 14:58
  • @PaulG. I've added all codes.
    – Sadegh
    Jun 13 '21 at 15:05
  • My familiarity with WP_Query is a bit limited, but instead of using that, have you tried get_posts() instead of any of the query stuff?
    – Paul G.
    Jun 13 '21 at 15:07
1

I've taken your code and refactored it. Your nested-for-loops arent the ideal way to go about this.

Also, I've used your code and the meta key names exactly as you supplied them, so please double-check they're correct. Some of them are prefixed with the_ and then sometimes not. It's strange, but that's what you supplied.

Try the code below to see if you get just 1 of each.

<?php
$page_id = get_the_ID();
$related_args = [
    'the_color'      => get_field( 'color', $page_id ),
    'the_background' => get_field( 'background', $page_id ),
    'the_lastname'   => get_field( 'lastname', $page_id )
];

$content = '';

foreach ( $related_args as $meta_key => $meta_value ) {

    $content .= $meta_value;  //to know the post after it are from that custom post

    $posts = get_posts( [
        'post_type'   => 'myposttype',
        'orderby'     => 'rand',
        'meta_key'    => $meta_key,
        'meta_value'  => $meta_value,
        'numberposts' => 1,
    ] );

    if ( !empty( $posts ) ) {
        $postID = current( $posts )->ID;
        $content .= sprintf( '<ul><li><a href="%s"><div class="post-image">%s</div><div class="post-title">%s</div></a></li></ul>',
            get_permalink( $postID ),
            get_the_post_thumbnail( $postID ),
            get_the_title( $postID )
        );
    }
    else {
        $content .= 'no posts found';
    }
}

echo $content;
1
  • very nice and clean code. it works. Thanks
    – Sadegh
    Jun 13 '21 at 16:08
0

I see that you are using ACF, but I wanted to give a solution where I go a little deeper in the process, and break it up in the different steps. I haven't used ACF, so this works without any plugins.

First, the functions

I broke out the different parts of what you needed into functions that could be reused at other places.

I also tried to write proper docblocks, so that if you have an editor that supports it, you will be reminded of what the functions does, and it will stop you from passing any variables of the wrong type.

This could be pasted into your themes functions.php, or a new file called fabians-functions.php and then just add the following line to functions.php.

require_once __DIR__ . '/fabians-functions.php';
/**
 * Get meta data key/value pairs.
 *
 * Pass an array of meta keys, get an array of
 * key/value pairs.
 *
 * @param array $meta_keys the meta keys you want to fetch.
 * @param int   $post_id the post ID you want to fetch them from.
 * @return array an associative array with meta_key => meta_value.
 */
function get_multiple_meta_values( array $meta_keys, int $post_id ) {
    $output_meta_key_value_pairs = array();
    foreach ( $meta_keys as $meta_key ) {
        $meta_value = get_post_meta( $post_id, $meta_key, true );
        if ( $meta_value ) {
            $output_meta_key_value_pairs[] = array(
                $meta_key => $meta_value,
            );
        }
    }
    // Flatten the array and remove any invalid entries.
    return array_merge( ...array_filter( $output_meta_key_value_pairs ) );
}

/**
 * Fetch posts with same meta vaues
 *
 * Pass in an associative array with the custom fields
 * you want to use to find similar posts.
 *
 * We will fetch one post per meta key/value passed.
 * We will not return the current post.
 * We will not return the same post twice.
 *
 * @param array $meta_collection an associative array with meta_key => meta_value.
 * @return WP_Post[] an array of WP Posts.
 */
function get_posts_with_same_meta( array $meta_collection ) {
    $output          = array();
    $wp_ignore_posts = array( get_the_ID() );

    // Now let's go trhough each of the meta fields you want to find posts on.
    foreach ( $meta_collection as $key => $value ) {

        $args = array(
            'post_type'      => 'post',
            // Only one posts.
            'posts_per_page' => 1,
            'post_status'    => 'publish',
            // That shares the first meta key/value pair.
            'meta_key'       => "$key",
            'meta_value'     => "$value",
            /**
             * Because we don't want to end up short, we need to
             * filter out any posts that was previously fetched.
             * We don't want duplicates to show up.
             */
            'post__not_in'   => $wp_ignore_posts,
        );

        $the_query = new WP_Query( $args );
        if ( $the_query->have_posts() ) :
            while ( $the_query->have_posts() ) :
                $the_query->the_post();
                // If we got a hit, add that post to $output[].
                $output[] = $the_query->post;
                // Also, add that posts ID to the ignore-list, so we won't fetch it again.
                $wp_ignore_posts[] = get_the_ID();
            endwhile;
        endif;
        wp_reset_postdata();
    }
    return $output;
}

Then, the fun

Now that we have everything set up, we can start using the functions in your page templates.

// Setup - Define the meta keys you wish to use.
$meta_keys_i_want_to_use = array( 'color', 'background_color', 'lastname' );

// Fetch the meta values from the current post and save in $wpm_meta.
// You can set any number of meta values.
$wpm_meta = get_multiple_meta_values( $meta_keys_i_want_to_use, get_the_ID() );

// Get posts.
$the_posts = get_posts_with_same_meta( $wpm_meta );

// Do what you want with them.
foreach ( $the_posts as $p ) {
    // The post is available as $p.
    ?>
    <div>
    <a href="<?php the_permalink( $p ); ?>">
    <h3><?php echo esc_html( $p->post_title ); ?></h3>
    <img src="<?php echo esc_attr( get_the_post_thumbnail_url( $p, 'thumbnail' ) ); ?>"></a>
    </div>
    <?php
}

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.