WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

My setup is as follows

I hava a custom post type named 'events' and a custom post type named 'genres' which I link with scribu's Posts2Posts plugin. Each event can have multiple genres linked to it.

What I would like to do

On an event page, I'd like to show other, related, events based on the genres the current event has.

What I think I should do

  1. Run a query which gets all the genres IDs of the current event
  2. Pass these IDs in a second query which finds all the events which have one or more of these genres linked to it

I have a p2p query which I'd like to output all events which have one AND / OR more of the given genres in connected_items. I pass them as an array, just like in the documentation.

To illustrate my outcome, lets say that

  • event1 has linked genres with post ids 1240, 1241, 1242 and 1250
  • event2 has linked genres with post ids 1240, 1241 and 1260
  • event3 has linked genres with post ids 1241 and 1242

In the first query I get all the genre IDs, this works.

The second query which gets all the events with the given genres (I pass them as an array):

$args = array(
        'connected_type' => 'genres_to_events',
        'connected_items' => array(1240,1241,1242),
        'post_status' => 'publish',
        'posts_per_page' => -1,

$query = new WP_Query($args);

The thing is that the output checks for each connection in the array, and therefor the output of the query is:

  • event1
  • event1
  • event1
  • event2
  • event2
  • event3
  • event3

But I'd like to output each event once based on if it has one or more of the genres connected to it. I don't think this is explained in the documentation, any ideas?

share|improve this question

closed as off-topic by birgire, Pieter Goosen, Johannes Pille, mrwweb, ialocin Sep 20 '14 at 12:19

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Your question should be specific to WordPress. Generic PHP/JS/HTML/CSS questions might be better asked at Stack Overflow or another appropriate site of the Stack Exchange network. Third party plugins and themes are off topic." – birgire, Pieter Goosen, Johannes Pille, mrwweb, ialocin
If this question can be reworded to fit the rules in the help center, please edit the question.

When you say p2p I keep thinking of scribu's plugin Posts 2 Posts - Is that what you are referring to? – GhostToast Aug 27 '13 at 14:05
Yes that's right, sorry for not mentioning. I'll update my question. – eskimo Aug 27 '13 at 17:29
When you get connected_items why use an array instead of the current $post->ID, as one would do while in a loop? Seems are you are combining the looping method of p2p and the single method, into one strange method. github.com/scribu/wp-posts-to-posts/wiki/each_connected – GhostToast Aug 28 '13 at 20:01
That would get the genres for each event. What I like to do is: when on an event page, get the genres for that event (this is working) and then (still on this event page) show other events which also have one or more of these genres attached to it. The last part isn't working. I've updated my question to illustrate the problem more clearly. – eskimo Aug 29 '13 at 7:36
up vote 0 down vote accepted

Ah I think I understand. I think what you should do with your first loop, is get the connected genres as you say. Then you wish to get all events that are related to those, so you should gather only the IDs (collect them in one array) in a loop, and then use array_unique() to remove all the duplicates. Use this clean array in a loop to get just those posts then. Make sense?

So, something like this might work:

$args = array(
        'connected_type' => 'genres_to_events',
        'connected_items' => array(1240,1241,1242),
        'post_status' => 'publish',
        'posts_per_page' => -1,

$query = new WP_Query($args);

$connected_out = array();

while($query->have_posts()) : $query->the_post();
    $connected_out[] = $post->ID;

$connected_out = array_unique($connected_out);

$args = array(
    'post__in' => $connected_out;

$query = new WP_Query($args);
// go!
share|improve this answer
Thanks! I've figured that I can use $related = p2p_type('genres_to_events')->get_related($query, array(), 'events');. Then use a while loop just like a normal with a normal wp_query to get the related posts. I can then use your method to filter out the duplicates (I'll try that step first). Then I've got one question left; how can I use more arguments in this query (like meta_compare etc)? We're almost there! I'll try your method for removing duplicates with the $related part first and update my question if it works. – eskimo Aug 29 '13 at 13:46
My previous comment was a bit stupid since I can just add that arguments to the last $args mentioned in your solution. I've combined your solution with the get_related method above and your solution works perfectly! (and I've now also learned about array_unique :-)) – eskimo Aug 29 '13 at 14:04
Cool. Glad that works for you! – GhostToast Aug 29 '13 at 14:16
Just encountered another problem. If I use the $related method as described above, it limits the results to 10 posts. This wouldn't work in my situation, since I have hundreds of events. So I'm back to using a query with connected_type etc to get an array of the posts (but the array_unique method is still useful of course). Will update when it works... – eskimo Aug 29 '13 at 21:07
'posts_per_page' => -1 -- a limit of 10 might need overridden somewhere. Look into that. – GhostToast Aug 29 '13 at 21:08

I'm posting this as an answer since it partially is and because I need some more characters than available in the comments. Hope that's OK :-).

So I've found the posts_per_page issue after reading this post.

It's possible to pass arguments to the get_related function, although it seems like you'd have to modify the p2p core. What I did was add my own get_related function, named my_get_related.

Code is as follows:

public function my_get_related( $item, $extra_qv = array(), $output = 'raw' ) {
        $extra_qv['fields'] = 'ids';

        $connected = $this->get_connected( $item, $extra_qv, 'abstract' );

        $additional_qv = array( 'p2p:exclude' => _p2p_normalize( $item ), 'posts_per_page' => -1 );

        return $this->flip_direction()->get_connected( $connected->items, $additional_qv, $output );

I've added this in wp-content/plugins/posts-to-posts/core/directed-connection-type.php (the original get_related function is on line 94).

You can see the 'posts_per_page' argument added, more can be easily added by separating them by commas.

Now I still have one question: how do I declare this function outside of the p2p core file? I don't want to add it there since it could backfire when updating the plugin. I'd like to add it to my functions.php (I use the Roots theme so it will be in some other file than functions.php but it's the same as putting it there since the file I'll put it in is an include of functions.php).

I've tried public function my_get_related... and add_action('p2p_init', 'my_get_related') but that doesn't work.

Any ideas on how to add this function outside of the core?

I think that after that, the problem is finally solved :-)

share|improve this answer
$connected = new WP_Query( array( 'connected_type' => 'posts_to_pages', 'connected_items' => get_queried_object(), 'nopaging' => true, ) ); -- it's all about the nopaging. github.com/scribu/wp-posts-to-posts/wiki/Basic-usage – GhostToast Aug 30 '13 at 12:05
True, but then I'd still not use the function get_related... The query you're suggesting would get me the genres, then I'd have to put them in a second query to get the related festivals. get_related does that in one go, so I'm hoping I can define the function outside of the plugin's core file. – eskimo Aug 31 '13 at 11:46

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