Bidirectional relations between multiple pages

Hello, I know it has been a topic before, there have been plugins and hacks to achieve that. But some time has passed and I don’t know what is the best way of doing it as of now: Connecting multiple pages as related.

I have an archive of multiple types of pages:

  • archive/blueprint1
  • archive/blueprint2
  • archive/blueprint3

Every page in that archive can be related to (m)any other pages. So in my blueprints I have this pages field called related:

related:
    type: pages

But I want this to be bi-directional: If a page1 is related to page2, page2 should also be related to page1. This should be visible in the panel as well as in the frontend, regardless of which of the 2 pages I am currently looking at. When removing the connection, it should be remove for both pages.

Keeping the connections in sync manually is too complicated, confusing and error-prone, so I am looking for an automatic solution.

As far as I can imagine, this could be approached by:

  • creating several hooks and whenever any page changes (content edited, deleted, unpublished), update all pages that are (or used to be) related to the current page. I have done this before for Kirby 3.0, so I know it’s possible but very complicated, slow and not uptodate
  • Using a plugin like the kirby3-many-to-many-field which I am not sure is uptodate

What is the best way of achieving this in 2023? :slight_smile:

Thank you for any hints…

As far as I can see, the plugin uses hooks as well to keep the relations up to date.

A flat file CMS is no database, so you will always have this issue when trying to keep stuff stored in multiple pages in sync, and likely also error-prone when you try to update a page that is currently being edited.

Maybe it would make sense to store this stuff in a database as a single source of truth and use a custom field that fetches its data from this database. Would require custom models that prevent data from this field being stored in the page, but instead in a database. No idea if this is feasible.

Just a quick thought: isn’t the way this is typically handled in a database that there is table A (containing data) and then there’s table B (storing the relationships between rows of table A)? Couldn’t this behavior be replicated with Kirby / a flat file CMS?

page.yml

# regular page blueprint

relationship.yml

# create relationship by saving related pages in a single pages field
fields:
  pages:
    type: pages

If you want to get the related pages of a page, you need to get all relationships where one of the pages is said page and then access to others from the pages field.

That way you only need to update one place (the relationship) if there are changes.