Skip Navigation

[Resolved] Filtering Views

This support ticket is created 3 years, 7 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 - -
13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 - -

Supporter timezone: America/New_York (GMT-04:00)

This topic contains 16 replies, has 2 voices.

Last updated by igorL-3 3 years, 7 months ago.

Assisted by: Christian Cox.

Author
Posts
#2058047
Filter.jpg

Tell us what you are trying to do? I have the following View:
....
<wpv-loop>
<tr>
<td>[wpv-post-link]</td>
<td>[wpv-view name="kennels-owner"]</td>
<td>[types field='established' format='FIELD_VALUE'][/types]</td>

<td>[wpv-view name="kennel-country"]</td>
<td>[wpv-view name="kennel-borzoi-bred-owned"]</td>
<td style="border-right: none;">[cred_delete_post_link post="Loading…" action="trash" message="Are you sure you want to permanently delete this Post?"
redirect="277002" class="cred-refresh-after-delete"]Delete[/cred_delete_post_link]</td>
</tr>
</wpv-loop>
<!-- wpv-loop-end -->
</table>
[wpv-pager-nav-links output="bootstrap" first_last_links="true" previous_next_links="true" reach="4"]
[/wpv-items-found]
[wpv-no-items-found]
[wpml-string context="wpv-views"]No Data[/wpml-string]
[/wpv-no-items-found]
[wpv-layout-end]

and for [wpv-view name="kennel-borzoi-bred-owned"] I have
<wpv-loop>
[wpv-post-link]
</wpv-loop>
where the filter is set as shown in the uploaded image. But I want to filter by [wpv-view name="kennels-owner"] from the first loop above not by [wpv-post-link] as is currently doing. Also I want to be able to have two filters in an OR, one fitering by Breeder relationship, as per image uploaded, an the other by Owner.

I've been trying to follow the post, link bellow, but not sure how to set it up

Is there any documentation that you are following?
https://toolset.com/forums/topic/displaying-related-posts-2/

Is there a similar example that we can see?

What is the link to your site?

#2058283

Hello, I'm not sure I understand what you mean here:
But I want to filter by [wpv-view name="kennels-owner"] from the first loop above not by [wpv-post-link] as is currently doing.
You want to filter a View by another View? I'm not sure I understand how this would work. Maybe if I understand a bit more about the post types involved and the relationships between these post types, I would be able to get a clearer idea about what you want to accomplish here.
- What post type is selected in the Content Selection for the main table View you described?
- What post type is selected in the Content Selection for the kennels-owner View - I assume it is Owner? What is the relationship between kennel and Owner: one-to-many (O2M) or many-to-many (M2M)? If it is O2M, which post type is the parent and which post type is the child?
- What post type is selected in the Content Selection for the kennel-country View - I assume it is Country? What is the relationship between kennel and country: one-to-many (O2M) or many-to-many (M2M)? If it is O2M, which post type is the parent and which post type is the child?
- What post type is selected in the Content Selection for the kennel-borzoi-bred-owned View?
- Which post types are involved in the Breeders relationship? What type of relationship is Breeders: one-to-many (O2M) or many-to-many (M2M)? If it is O2M, which post type is the parent and which post type is the child?
- Do you have a mockup or sketch of the desired filters and results?

Also I want to be able to have two filters in an OR, one fitering by Breeder relationship, as per image uploaded, an the other by Owner.
Custom search Views support a maximum of one post relationship search filter, so this type of filtering may not be supported. The main exception to this limitation involves a series of hierarchical O2M relationships, like grandparent > parent > child. In this scenario the grandparent post type is in a O2M relationship with the parent post type, and the parent post type is in a O2M relationship with the child post type. In this case, you can add multiple ancestor fields to the custom search filters to filter a View of child posts by grandparent and parent.

However, if you have two unrelated one-to-many post relationships, or if one of the post relationships is many-to-many, then this exception does not apply. Only one post relationship custom search filter is supported in those cases.

#2058345

Hello,

I've uploaded the dev site to a server. There are some errors but what I need help with works. So if you look here: hidden link
There is a list of Kennels. Each kennel has an owner (2nd column) and each owner also owns or has bred the dogs. So I want to be able to list the dogs that belong to the owner of the kennel or has been bred by him.

To answer your specific questions:

What post type is selected in the Content Selection for the main table View you described?
>>>I'm listing Kennels in the main table

What post type is selected in the Content Selection for the kennels-owner View - I assume it is Owner? What is the relationship between kennel and Owner: one-to-many (O2M) or many-to-many (M2M)? If it is O2M, which post type is the parent and which post type is the child?
>>>There is a M2M relationship called Owner between custom post Person and custom post Kennel

What post type is selected in the Content Selection for the kennel-country View - I assume it is Country? What is the relationship between kennel and country: one-to-many (O2M) or many-to-many (M2M)? If it is O2M, which post type is the parent and which post type is the child?
>>>Relationship Country is O2M where Country is ONE and Kennels is MANY

What post type is selected in the Content Selection for the kennel-borzoi-bred-owned View?
>> It's custom Post BORZOI (of type dog). There is a M2M relationship between custom type Person and custom type Borzoi

Which post types are involved in the Breeders relationship? What type of relationship is Breeders: one-to-many (O2M) or many-to-many (M2M)? If it is O2M, which post type is the parent and which post type is the child?
>>>This is a M2M relationship called Breeder between Person and Borzoi

- Do you have a mockup or sketch of the desired filters and results?
>>> See the link hidden link
>>>There is a list of Kennels. Each kennel has an owner (2nd column) and each owner also owns or has bred
>>>the dogs. So I want to be able to list the dogs that belong to the owner of the kennel or been bred by him.

Alternatively, if that will be better, I'd be happy with placing a link in the Borzoï Bred & Owned column in the table here hidden link which will list out all the dogs bred and owned by a given person in that table. And display it as here: hidden link
but clearly the owner will be one from the previous table

#2058497
kennel-row-1.png

So I want to be able to list the dogs that belong to the owner of the kennel or been bred by him.
There is a M2M relationship called Owner between custom post Person and custom post Kennel
Okay I understand a bit better now. Based on this information, I understand the relationship between Borzoi and Kennel is indirect. There is no direct relationship between Borzoi and Kennel. Is that correct, or is there also a direct post relationship between Borzoi and Kennel?

Since a Kennel can be related to multiple Persons (the Owner relationship is M2M), it is possible for one Kennel row to include multiple Owner Persons (see kennel-row-1.png). In the BORZOÏ BRED & OWNED column in this case, do you want to display one group of Borzoi posts, or do you want to display 3 separate groups of Borzoi posts - one group for each Person?

#2058857

As you noted the relationship between Borzoi and Kennel is indirect. There is no direct relationship between Borzoi and Kennel. There ought to be a direct relationship between Borzoi and Kennel but I’m stuck with what I have.

Although rare it is possible for one Kennel row to include multiple Owner Persons as you have suggested. In that case there should be just a group for all of the people because the dogs belong to the Kennel.

If this is possible that's great, an alternative, perhaps easier, is to place a link in the Borzoï Bred & Owned column that inserts the name of the Kennel into the search field on the List of Borzoï page. For example say the Kennel name is Aaronoff then the link should be: hidden link

The above works because the name of the Kennel is in the name of the dog

#2058923

If this is possible that's great, an alternative, perhaps easier, is to place a link in the Borzoï Bred & Owned column that inserts the name of the Kennel into the search field on the List of Borzoï page.
This is definitely possible with some custom filtering code. Whether you display the list of Borzoi here in this table or in another page does not change the approach much. In either location, a fair amount of custom code is required. I can help you implement the filter wpv_filter_query with our post relationships APIs to display the correct information in either location. I think it will be simplest to set it up in this table for now, and we can move it later if necessary.

Since there is no direct relationship between Kennel and Borzoi, it seems like the View of Borzoi must be filtered by one post relationship, based on the Breeder relationship, where the Breeder Person is any of the Owner Persons related to the current Kennel in the loop. We offer the post relationship API toolset_get_related_posts, which can help find Borzois related to specific Persons:
https://toolset.com/documentation/customizing-sites-using-php/post-relationships-api/#toolset_get_related_posts
In the arguments section, the first argument can be specified in the format "Arrays of arrays of posts indexed by role names: The function will return only posts that are connected to any of the provided posts for each role."
Example:

array( 'parent' => array( $parent1, $parent2 ), 'intermediary' => $intermediary1 )

This returns posts connected to $parent1 or $parent2 in the parent role, and to the $intermediary1 in the intermediary role. That's what you need here, Borzois connected to any of the Persons related to the current Kennel.

So to implement this post relationship API to query the Breeder relationship, you need to know which post type is the parent and which type is the child. It is not always obvious, so you should go to Toolset > Relationships and edit the Breeder relationship. Check the confirmation checkbox "I understand that changes to these settings may delete post associations in this Relationship" and click Edit Relationship.
1. You need to know which post type is the parent and which is the child
2. You need to know the slug of the Breeders post relationship

Next, you need to plug into the API the IDs of the Persons who are Owners of the current Kennel in the loop. Luckily you already have a View created that can be used to get that information, the "kennels-owner" View. You can use the PHP API get_view_query_results to get the results of that View in PHP:
https://toolset.com/documentation/programmer-reference/views-api/#get_view_query_results
3. You need to know the ID of the kennels-owner View to get the results of this View easily in PHP

Knowing the Person IDs, you can filter the "kennel-borzoi-bred-owned" View of Borzoi posts using the wpv_filter_query API and apply the results of the toolset_get_related_posts API. In the View editor screen for "kennel-borzoi-bred-owned", you should remove any post relationship Query Filters you may have already set up.
4. You need to know the numeric ID for the kennel-borzoi-bred-owned View.

Putting it all together, the wpv_filter_query looks like this simplified version:

// In a View of Kennels, show Borzoi bred by any Person who is Owner of current Kennel in the loop
// Reference: https://toolset.com/forums/topic/filtering-views/
add_filter( 'wpv_filter_query', 'tssupp_kennel_borzoi_bred_owned', 99, 3 );
function tssupp_kennel_borzoi_bred_owned( $query_args, $view_settings, $view_id ) {
    $views = array( 123 ); // replace 123 with the numeric ID of the kennel-borzoi-bred-owned View
    if( in_array( $view_id, $views ) ) { // only filter the kennel-borzoi-bred-owned View, by ID
        $owners = get_view_query_results(...); // get the results of the kennels-owner View as post objects
        $borzoi = toolset_get_related_posts(...); // get borzoi bred by $owners
        $query_args['post__in'] = $borzoi; // fetch those borzoi posts by ID
    }
    return $query_args;
}

So the next step is geting those items 1-4 listed above. Then we can plug that information into the custom code example and flesh it out a bit. I can help you get this set up if you need assistance. Just let me know what you're able to achieve with PHP, if you get stuck somewhere, or if you have no idea how to proceed here just share items 1-4 listed above and I can show you the next steps.

#2060223

Hello,

It sort of works but there are issues. This is the current code with diagnostic var_dumps()

add_filter( 'wpv_filter_query', 'tssupp_kennel_borzoi_bred_owned', 99, 3 );
function tssupp_kennel_borzoi_bred_owned( $query_args, $view_settings, $view_id ) {
$views = [292457]; // numeric ID of the kennel-borzoi-bred-owned View

if( in_array( $view_id, $views ) )
{ // only filter the kennel-borzoi-bred-owned View, by ID
$owners = get_view_query_results(292451);
// get the results of the kennels-owner View as post objects
echo('$owners');
echo('<br>');
var_dump($owners[0]->post_title);
echo('<br>');
// get borzoi bred by $owners
$borzoi = toolset_get_related_posts(
[
'parent' => $owners
],
'breeder-dog-person'
);
echo('$borzoi');
echo('<br>');
var_dump($borzoi);
echo('<br>');
$query_args['post__in'] = $borzoi; // fetch those borzoi posts by ID
}
return $query_args;
}

If it doesn't find $borzoi it throws an error
$owners
string(13) "Donald Hoflin"
$borzoi
array(0) { }

Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 20480 bytes) in /var/www/vhosts/borzoipedia.com/wordpress.borzoipedia.com/wp-content/plugins/types/vendor/toolset/types/embedded/classes/loader.php on line 91

Now if I change the sorting so that it starts with Z in List of Kennels it does work but it places the same dog for all Kennel entries as in here: hidden link

This also happens if the relationship slug is changed to breeder-dog-person. It seems it cycles through the filter only once and uses the output for all other entries

And if I make a change to the code I need to clear the cached for the View with ID 292457 (Kennel Borzoï Bred & Owned)

#2060359

Okay let's check first to see if the $owners results are filtered appropriately:

// get the results of the kennels-owner View as post objects
echo('$owners');
echo('<br>');
echo('number of owners: ' . count( $owners) . '<br>' );
var_dump($owners[0]->post_title);
echo('<br>');
#2060447
Untitled copy.jpg

It's finding one owner
number of owners: 1
which is ok becaues vast majority of Kennels have one owner but it's just not cycling to the other kennels in the view.
Can the issue be the filter in view ID 292451 (Kennels Owner) see atached screenshot

#2061281

I think I found the problem. Not all Kennels had dogs listed and when no dogs were returned it piked the first it would find, similarly for owners. If no owners were returned it returned the limit parameter of dogs, ie 100 or threw an error. So I added the following lines:
$borzoi = empty( $owners ) ? array(0) : toolset_get_related_posts(
[
'parent' => $owners
],
'breeder-dog-person'
);

and
$query_args['post__in'] = empty( $borzoi ) ? array(0) : $borzoi;

that seemed to have hellped

still need to check if the data is correct but at least the code works somewhat

#2061315

So it seems to be working now. I have two questions regarding this issue:

1. Is its possible to get related posts by more than one slug. In the following code
$borzoi = toolset_get_related_posts(
[
'parent' => $owners
],
'breeder-dog-person'
);

the slug is 'breeder-dog-person' but I also want relationships of the 'owner-dog-person' slug. How can I do that as using
['breeder-dog-person', 'owner-dog-person'] not going to work

And

2. Is there a simpler way to do this. For example create a relationship between Borzoi <<<>>> Kennel then run a script to fill a field in custom post Kennel to Borzoi to associate the kennel or the Borzoi. Using something like toolset_connect_posts(). If so could you please guide me how to set this up.
I ask this becasue when I made a form to create new Borzoi I included the field Kennel to avoid this issue with future post.

#2061593

1. Is its possible to get related posts by more than one slug...I also want relationships of the 'owner-dog-person' slug. How can I do that as using
['breeder-dog-person', 'owner-dog-person'] not going to work

Sorry, I am unaware of the owner-dog-person relationship and its configurations, but, if I understand correctly, you are saying you have two post relationships between Persons and Borzois. One is the breeder-dog-person relationship and the other is the owner-dog-person relationship. You would like to find all the Borzoi related to a single known Person, querying in both post relationships. Unfortunately that is not possible in a single API call to toolset_get_related_posts. This API only accepts one post relationship per query. Multiple API calls are required to query related posts from multiple post relationships. Then you could use PHP's array functions like array_merge to combine those two sets of results, producing an array of related Persons from both relationships: https://www.php.net/manual/en/function.array-merge.php

2. Is there a simpler way to do this.
Well if you create a direct relationship between Kennel and Borzoi, it would be much simpler to display the list of Borzoi for each Kennel in the table. Displaying this information would require no additional custom code, just one View of Borzoi with a post relationship Query filter based on the current Kennel post in the loop, or based on a shortcode attribute where you pass in the current Kennel post ID.

Managing this relationship with Forms will be simpler if the post relationship is O2M, where the Kennel is parent and the Borzoi is child. If a post relationship is O2M, no additional custom code is required to manage this relationship in a Form that creates child (Borzoi) posts. The Form builder can automatically insert a post relationship field in a Form that creates or edits Borzoi posts, and you do not need to use custom PHP like toolset_connect_posts or anything like that to connect the Kennel and Borzoi when the Form is submitted. Forms automatically handles that association.

#2061663

Regarding your answer to question 1: Yes there is an assosiation between owner and Borzoi. But now that I know how to filter the results I can do what you have suggested and merge the two resulting array, remove duplicated ID's and return it all in $query_args[‘post__in’] .

Regarding your answer to question2: I didn’t explain myself fully. I have already implemented the form and the association between Borzoi and Kennel and it works. What I was now asking was about updating the old records. I have now 16k Borzoi custom posts and I now want to make the association with a Kennel as it is now done in the form. This is a one off to update the database for all the old custom posts.

The procedure itself is simple. Cycle through all the KENNEL posts and using toolset_connect_posts() connect it with all the Borzoi posts that have the Kennel post_title in the post_title of Borzoi. The post_title of Borzoi will be longer than post_title of Kennel so it would be a matter of finding all the Borzoi posts where the post_title contains a given string and making a connection.
There are few Borzoi posts that do not have the name of the Kennel in the post_title but they are not many and if I get them into a file then they can be corrected using the form I alredy implemented.

I know how to get the IDs from posts and I’ve already set up the relationship Borzoi<<>> Kennel and I know how to use toolset_connect_posts(). What I’m not sure is how to set it up in custom code to do a one off run.

#2061717
Screen Shot 2021-05-19 at 11.56.09 AM.png

I know how to get the IDs from posts and I’ve already set up the relationship Borzoi<<>> Kennel and I know how to use toolset_connect_posts(). What I’m not sure is how to set it up in custom code to do a one off run.
One simple way is to create a custom code snippet in Toolset > Settings > Custom Code and set it to run only "On demand". Then you can click "Run now" or "Save and Test", and the code will run once.

Your code snippet could define a custom function, then invoke the function:

...
// Put the code of your snippet below this comment.

// define a function to loop over posts and set relationships programmatically
function set_relationships_once() {
  // add your code here
}

// invoke the function
set_relationships_once();

When you click the "Save and Test" button the code will be executed once. Or, you can click "Save" and then "Run now". Either method will execute the code once. You can delete the custom code snippet afterwards since you only want one run.

#2061757

I understand that. How do I cycle through all the custom posts of a particular type. Is it best to create a VIEW and then use get_view_query_results(...) or is there a way to do something like foreach($KENNELS as $kennel){...}