wp-posts-to-posts icon indicating copy to clipboard operation
wp-posts-to-posts copied to clipboard

only one object on many-side of one-to-many relationship is being connected to its related post

Open sdrori opened this issue 12 years ago • 2 comments

We have a one-to-many relationship between two types of posts (which is the correct cardinality for this relationship) and a page that presents a gallery of 'p2p_to' post type objects.

Because the page displays the 'to' objects (the 'many'-side of the many-to-one relationship) we need to be able to fetch all related 'from' objects relate them to one OR MORE of the 'to' objects.

The problem is, whether we use WP_Query directly or go through each_connected(), only one instance of the 'from' post is returned and the p2p_to property of that object contains only a single 'to' post ID (instead of, say, an array of related 'to' post ID's).

Because of this p2p_distribute_connected() can only map each connected object to one of the source objects.

Is there a way to alter this behavior in the query, some query extra _p2p parameter that needs to be set?

sdrori avatar Oct 11 '13 20:10 sdrori

Some additional information: Because the original page query included taxonomy terms WP_Query adds a GROUP BY to the query. As a result the connected object query has a group by clause as well.

I am able to get around this by adding a 'posts_groupby' filter that appends ", {$wpdb->p2p}.p2p_id" and then removing it immediately after I fetch the connected posts. This works, but it changes the linking property from an object to an array (not sure why) and adds the additional group by field to the sub-query as well (this isn't a problem here, but it is unintentional).

In the end, rather then adding WP filter to modify the GROUP BY clause I just wrote my query to fetch the p2p records and then to map the tagged posts to their connected posts. But I'm still curious if there is a simpler way to address this type of situation (fetching the 'one' side for each of the 'many' side objects in a 'one-to-many' relationship).

Here's the relationship definition:

p2p_register_connection_type( array(
    'name'              => 'designs_to_design_variation',
    'from'              => 'design',
    'to'                => 'design_variation',
    'cardinality'       => 'one-to-many',
    'sortable'          => 'any',
));

And, here's the query WP_Query generates:

SELECT 
    wp_4_posts . *, wp_4_p2p . *
FROM wp_4_posts
INNER JOIN wp_4_term_relationships ON (wp_4_posts.ID = wp_4_term_relationships.object_id)
INNER JOIN wp_4_p2p # join conditions in the where clause
LEFT JOIN wp_4_p2pmeta AS p2pm_order ON (wp_4_p2p.p2p_id = p2pm_order.p2p_id AND p2pm_order.meta_key = '_order_to')
WHERE 1 = 1
AND (wp_4_term_relationships.term_taxonomy_id IN (288))
AND wp_4_posts.post_type = 'design'
AND (wp_4_posts.post_status = 'publish' OR wp_4_posts.post_status = 'private')
AND (
    # this is the p2p type
    wp_4_p2p.p2p_type = 'designs_to_design_variation'
    AND wp_4_posts.ID = wp_4_p2p.p2p_from
    AND wp_4_p2p.p2p_to IN (
        SELECT wp_4_posts.ID
        FROM wp_4_posts
        INNER JOIN wp_4_term_relationships ON (wp_4_posts.ID = wp_4_term_relationships.object_id)
        WHERE 1 = 1 AND wp_4_posts.ID IN (15547 , 15544, 15541, 15539, 15536, 15534, 15532, 15530, 15528, 15526, 15523, 15520, 15518, 15516, 15514, 15511, 15510, 15509, 15508, 15489)
        AND (wp_4_term_relationships.term_taxonomy_id IN (288))
        AND wp_4_posts.post_type = 'design_variation'
        AND (wp_4_posts.post_status = 'publish' OR wp_4_posts.post_status = 'private')
        GROUP BY wp_4_posts.ID
        ORDER BY wp_4_posts.post_date DESC
    )
)
GROUP BY wp_4_posts.ID
ORDER BY p2pm_order.meta_value + 0 ASC , wp_4_posts.menu_order ASC;

sdrori avatar Oct 14 '13 18:10 sdrori

Hello! I have the same issue here. One-to-many relationship and each_connected() returns only one instance of "from" objects. I found solution by using this wp filter and removing group_by from wp_query that are used for selecting connected posts in each_connected function.

add_filter( 'posts_groupby', 'my_posts_groupby' ); function my_posts_groupby($groupby) { global $wpdb; $groupby = ""; return $groupby; }

magicworks avatar Mar 15 '15 20:03 magicworks