Hi there
I have a need to display a list of Questionnaires. They are children of both Process and Client.
Translated into human language - the usage is : a Client completes Questionnaires related to a Process.
So in the view, I would like to show the Questionnaires that are the children of both a specific Process and a specific Client.
As I see it, the query filter only allow one post relationship filter, and I need two for this (with a boolean AND between).
So for now I have made the post relationship filter on the Process and then I have a conditional output in the loop where I filter for Client.
However, that is probably les DB effective, and also it restricts me from using other view features like "no-items-found".
What can I do differently / better?
Hi, you can add some custom code that uses the wpv_filter_query API to extend the meta query for this View, and remove the conditionals you have in the results. Child posts are related to each of their parent posts in the postmeta table with a key in the format "_wpcf_belongs_" + parent post type slug + "_id". An example that adds two parent post type filters to a View's query:
add_filter( 'wpv_filter_query', 'multi_parent_filter', 10, 3 );
function multi_parent_filter ( $query, $view_settings, $view_id ) {
$views = array( 1234, 5678 );
if( in_array($view_id, $views) ) {
$args = array(
'relation' => 'AND',
array(
'key' => '_wpcf_belongs_parent-type-slug-1_id',
'value' => 9876,
'compare' => '=',
'type' => 'numeric'
),
array(
'key' => '_wpcf_belongs_parent-type-slug-2_id',
'value' => 5432,
'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;
}
If you need to add or remove more parent post types, copy or delete an entire block for each parent post type like this:
array(
'key' => '_wpcf_belongs_parent-type-slug-1_id',
'value' => 9876,
'compare' => '=',
'type' => 'numeric'
),
Replace 1234, 5678 with a comma-separated list of View IDs where you would like to apply this filter. Replace the keys like '_wpcf_belongs_parent-type-slug-1_id' and '_wpcf_belongs_parent-type-slug-2_id' with the proper keys for each post type, formatted as described above. Replace 9876 and 5432 with the numeric IDs of the parent post for that block's particular post type. If these are not predefined IDs, you must use variables defined by some other criteria. For example if your Users select these parent posts on the front-end with a filter, you must create a custom filter or filters and capture the selected values from the $_POST superglobal. I can help with that if you need assistance.
Hi Christian
Thanks, this filter is very useful. I actually wish a had searched for this earlier. Could have streamlined our development a bit more.
Am I correct in assuming that this plugin filter adds to the filter defined in Views?
If so, how is the boolean relation between them handled (AND or OR)?
If not, how do I, in the plugin filter, test for a value from the "Post where this View is shown"?
I need the view to return one (1) result of CPT Quest1 where
- _wpcf_belongs_client_id is equal current logged in users client id (got that covered in the plugin) AND
- _wpcf_belongs_process_id is equal the ID of the Process (post) where the view is shown AND
- wpcf_current is equal 1 (current is a Types checkbox field on Quest1)
Thanks.
Am I correct in assuming that this plugin filter adds to the filter defined in Views?
Yes and if no relationship operator exists yet, the default is "AND".
I need the view to return one (1) result of CPT Quest1 where
- _wpcf_belongs_client_id is equal current logged in users client id (got that covered in the plugin) AND
- _wpcf_belongs_process_id is equal the ID of the Process (post) where the view is shown AND
- wpcf_current is equal 1 (current is a Types checkbox field on Quest1)
It's easier to determine the current User's ID in code than it is to determine the current page in code, so I recommend changing the post relationship query in your View editor to filter the parent Process, set by the current page or post. Then you can use get_current_user_id to get the current User ID. More information about that API here.
https://developer.wordpress.org/reference/functions/get_current_user_id/
add_filter( 'wpv_filter_query', 'multi_parent_filter', 10, 3 );
function multi_parent_filter ( $query, $view_settings, $view_id ) {
$views = array( 1234, 5678 );
$user_id = get_current_user_id();
if( in_array($view_id, $views) ) {
$args = array(
'relation' => 'AND',
array(
'key' => '_wpcf_belongs_client_id',
'value' => $user_id,
'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;
}
The "current" field filter and the parent process filter will be maintained from the View editor.
Hi Christian
Thanks - as you can see in the below code, this is what I ended up with ?
So I have the "current" field filter and the parent post filter in the View, and the below in my plugin as an addition.
Works nicely.
add_filter( 'wpv_filter_query', 'multi_parent_filter', 99, 3 );
function multi_parent_filter ( $query, $view_settings, $view_id ) {
$views = array( 123, 124 );
$user_client_id = get_user_meta(get_current_user_id(), 'wpcf-userclientid', true);
if( in_array($view_id, $views) ) {
$args = array(
array(
'key' => '_wpcf_belongs_client_id',
'value' => $user_client_id,
)
);
// add these arguments to your meta query
$query['meta_query'] = isset($query['meta_query']) ? $query['meta_query'] : [];
$query['meta_query'][] = $args;
}
return $query;
}