I have a many to many relationship:
Book <-- Contributor --> Author
A book can have multiple authors, an author can have multiple books.
I know the ID of the book, and I know the ID of the author (post id). What I need to be able to do is create a view that finds the contributor record between them.
For example, /contributor-page?bookid=123&authorid=432
Take this and feed this into a view that returns the contributor record that states:
Author ID 432 contributed to Book ID 123.
The problem is that in the view settings, I can declare "is a child of" only once.
Is there a way to add a second filter through some other means? Why can't I just reference the actual data in the field (e.g. wcfp_postname or wherever that data is stored)?
Is there a way to add a second filter through some other means?
If you add one post relationship filter, let's say author ID, then you can add conditional HTML in that View's output that will test the book parent against a URL parameter. This shortcode will allow you to access any URL parameter:
add_shortcode( 'wpv-post-param', 'wpv_post_param_shortcode' );
function wpv_post_param_shortcode( $atts ) {
if ( !empty( $atts['var'] ) ) {
$var = (array)$_GET[$atts['var']];
return esc_html( implode( ', ', $var ) );
}
}
Then you can use conditional code like this:
[wpv-conditional if="( '[wpv-post-id id='$book']' eq '[wpv-post-param var='bookid']' )"]
This will be displayed for the matching intermediary post.
[/wpv-conditional]
Why can't I just reference the actual data in the field (e.g. wcfp_postname or wherever that data is stored)?
The reference between a parent and child post is stored as a hidden postmeta value on the child post, so it's not accessible in the GUI to be assigned to a filter. If you want to access that field in PHP, the key syntax is "_wpcf_belongs_parentslug_id". So if your parent slug is book, the syntax is "_wpcf_belongs_book_id".
We're currently making some big changes to the way Many to Many relationships are handled and displayed, so this process is going to be smoother in upcoming releases. There's currently a beta version of the Types side of this available, but there's not yet a beta version showing how this will be implemented in Views. Let me know if you have additional questions here.
Hey Christian,
Thanks for the quick reply. I am aware of the workaround you've suggested, but unfortunately, I need to know when no results are returned.
E.g. If Author A has not contributed to Book B, then I need to be able to create a line that says "Author A has not contributed to Book B" (using the no results found within the view).
The conditional would result in the not generating the "no results" segment.
I am closely following v2.3, but I have to solve this one immediately.
I've tried feeding the IDs of both parents into a view, but this gives all related posts to both (outer join), when I need an inner join...
Any other ideas? Thanks again!
I came up with an extremely hacky solution. Is this safe to use?
(it appears to work)
[wpv-view name="testtest" parent1="10243" parent2="10723"]
testtest is a view selecting contributors, limited to related authors (parent 1)
-this view calls another view inline (see below), feeding the list of ids from this view
testtest2 is a view selectin contributors, limited to related books (parent 2)
(this view is fed a list of IDs from view1, in addition to the parent2 id
(view testtest)
[wpv-layout-start]
[wpv-items-found]
<!-- wpv-loop-start -->
[wpv-view name="testtest2" parent2="[wpv-attribute name="parent2"]" ids="
<wpv-loop>
[wpv-post-id],
</wpv-loop>"]
<!-- wpv-loop-end -->
[/wpv-items-found]
[wpv-no-items-found]
<strong>[wpml-string context="wpv-views"]No items found[/wpml-string]</strong>
[/wpv-no-items-found]
[wpv-layout-end]
I was a bit surprised that views would allow me to nest an entire loop statement into an argument to another view. Is this a viable solution or am I apt to run into issues down the line?
Any cleaner ideas/solutions would be greatly appreciated... thanks again!
I think I was drafting my response while you were writing yours. The better solution is to filter the query using wpv_filter_query. You can add two hidden input fields into your View's filter controls. One can capture the value of parent A and the other can capture the value of parent B, using the wpv-post-param shortcode I mentioned earlier. In the Filter Controls panel, add this code inside the wpv-filter-controls tags:
<input type="hidden" value="[wpv-post-param var='bookid']" name="bookid" /><input type="hidden" value="[wpv-post-param var='authorid']" name="authorid" />
Then in your functions.php file, add the following code:
add_filter( 'wpv_filter_query', 'filter_both_parent_types', 10, 3 );
function filter_both_parent_types ( $query, $view_settings, $view_id ) {
if( $view_id == 1234 ) {
$selected_parent1 = isset($_GET['bookid']) ? $_GET['bookid'] : null;
$selected_parent2 = isset($_GET['authorid']) ? $_GET['authorid'] : null;
$args = array(
'relation' => 'AND',
array(
'key' => '_wpcf_belongs_book_id',
'value' => $selected_parent1,
'compare' => '=',
'type' => 'numeric'
),
array(
'key' => '_wpcf_belongs_author_id',
'value' => $selected_parent2,
'compare' => '=',
'type' => 'numeric'
)
);
// add these arguments to your meta query
$query['meta_query'] = isset($query['meta_query']) ? $query['meta_query'] : [];
$query['meta_query'][] = $args;
}
return $query;
}
Change "1234" to match your View's ID.
Awesome thanks so much Christian. I'll give this a shot and report back if I run into any issues.