Get reverse relation for related items of a page (from "one to many" to "many to many")

Hello here :waving_hand:

My website is for a book festival. Hundred of books are featured and there’s also a program with different events.

First, we wanted to point from a book page to related events. I’ve added a field of type pages in the blueprint querying for events in book.yml and it’s great.

But now, I’m asked if I can display from the Event page, the related books. Meaning, books which have this event in its relatedEvents field.

Is there a more elegant and efficient way than looping through all books for each event page?

In a database thinking, this operation would be like switching from a “one to many” relation to a “many to many” relation I guess.

I was wondering about this plugin GitHub - jonasholfeld/kirby3-many-to-many-field: This plugin allows you to create many-to-many relationships between pages in Kirby and synchronizes them on both sides. Latest version also works with Kirby 4! but maybe there’s a way that doesn’t depend on an external component?

Thanks for your help

If you only need this relation on the frontend, you can filter the books on the specific event page by whethere they have this event or not:

$booksForEvent = page('books')->children()->listed()->filter(fn($book) => $book->relatedEvents()->toPages()->has($page));

The plugin you mentioned above actually stores this reverse relation in the events pages via hooks, personally, I’m not really a fan of such an approach, unless it’s really needed.

Having said that, filtering all books every time can have disadvantes as well if there are thousands of books, and therefore some sort of caching (e.g. via the standard page cache) would make sense.

Hi @texnixe thank you for your help. I forgot about the filter function, I’ll start with that for the moment. With cache enabled.

Small tangent, but if you need to use the same logic for querying the books for an event in different places (in templates, in the panel, etc.), you can create a page model with a custom function.

If you need to display the books for an event on the event’s page in the panel, but don’t want to allow modifying the books from there, I found that using this old plugin works well:

It’s not maintained and I had to tweak the code to make it work with Kirby 4. Using the built-in Pages section works too, but allows actions like deleting a page or changing its visibility, which would probably lead to chaos as Panel users use “Delete” with the intent to remove a relationship but end up removing the page itself.

1 Like