This plugin allows you to create many-to-many relationships between pages in Kirby and synchronizes them on both sides.

Overview

Kirby 3 Many To Many Field

This plugin allows you to create many-to-many relationships between pages in Kirby. The relationship is bidirectional, meaning it can be edited from either side and is automatically updated on the other side. The relationship can have attributes that can be updated from both sides as well. You can define multiple many-to-many relations on one page. If a page with a relation to one or many other pages gets deleted, all relations to this page get deleted as well.

You need to install the AutoId plugin by Bnomei to your project as well for this plugin to work.

This plugin uses two hooks: the page.update:after and the page.delete:before hook. If you use these hooks in your project as well, make sure to rename the hooks and trigger them seperately as described here.

many-to-many-kirby3

Installation

Download

Download and copy this repository to /site/plugins/kirby3-many-to-many-field.

Git submodule

git submodule add https://github.com/jonasholfeld/kirby3-many-to-many-field.git site/plugins/kirby3-many-to-many-field

Composer

composer require jonasholfeld/kirby3-many-to-many-field

Setup

  1. Install AutoID
  2. Use AutoID to identify your pages
  3. Setup your blueprints

1. Install AutoID

Add the AutoID plugin by Bnomei to your kirby-project.

2. Use AutoID to identify your pages

Both blueprints of the pages you want to have a many-2-many relation need to have this field:

autoid:
  type: hidden
  translate: false

The AutoID plugin automatically generates a unique ID for every page that will be created after it’s install. If some pages already exist without an ID, you can force a re-index.

3. Setup your blueprints

The many-to-many plugin gets all its information about the related pages from your blueprints, so it’s essential to set them up right. You can check out the example blueprints to get a better idea about how to setup yours.

Both blueprints need the manytomany field in order to connect the pages correctly. As it’s important to set them up correctly, the following text explains every step bit by bit.

3.0.1 Quickstart

You can use and adjust these two blueprints to setup a relation between two pages with the plugin. It implements the classic Employee <--> Project relation you might know from database examples (see ER-diagram above). Make sure to rename all fields according to your situation. To fully understand all the fields and adjust them to your situation you should read on.

project.yml

title: Project

fields:
  description:
    type: text
    label: Description

  employees:
    type: manytomany
    label: Employees
    fields:
      foreignkey:
        label: Employee
        type: multiselect
        min: 1
        max: 1
        options: query
        query:
          fetch: site.find('employees').childrenAndDrafts
          text: "{{ page.title }}"
          value: "{{ page.autoid }}"
      hours:
        type: number
        label: Number of hours
    validate:
      unique: employees
    relatedPage: employees
    relatationField: projects
    
  autoid:
    translate: false

employee.yml

title: Employee

fields:
  age:
    type: number
    label: Age

  projects:
    type: manytomany
    label: Projects
    fields:
      foreignkey:
        label: Project
        type: multiselect
        min: 1
        max: 1
        options: query
        query:
          fetch: site.find('projects').childrenAndDrafts
          text: "{{ page.title }}"
          value: "{{ page.autoid }}"
      hours:
        type: number
        label: Number of hours
    validate:
      unique: projects
    relatedPage: projects
    relatationField: employees
    
  autoid:
    translate: false

3.1 Naming and Type

You can name the field how you like. A name hinting to the nature of the relation or the templates of the related pages might be helpful.

You need to specify the type as manytomany:

myRelatedPages: #<-- name how you like
  type: manytomany
...

The manytomany-field inherits from the structure field, so it is setup like a normal structure-field with a couple of additional fields that need to be filled.

3.2 The foreignkey field

The foreignkey field is the field inside our manytomany-field that saves the "foreign keys". In our case they are the IDs created by the autoID plugin. You create a field inside the manytomany-field called "foreignkey" that is a multiselect that queries its options from the pages you would like to link to. To be more specific, it queries the children of a given page, so you need to specify the name of the parent-page to whose subpages you would like to link to. It is important to use page.autoid as the value, you can chose what to use as the text, but I recommend to use page.title to identify the pages.

myRelatedPages:
  type: manytomany
  lable: My Related Pages
  fields:
    foreignkey: #<-- name needs to be *foreignkey*
      label: Related Page
      type: multiselect
      min: 1
      max: 1
      options: query
      query:
        fetch: site.find('myRelatedParentPage').childrenAndDrafts # <-- use name of parent-page of related pages here
        text: "{{ page.title }}"
        value: "{{ page.autoid }}"
  validate:
    unique: myRelatedPages
...

3.3 The unique validator

Duplicate entries inside the manytomany field cause problems, so make sure to use the unique validator of the plugin:

myRelatedPages:
  type: manytomany
  lable: My Related Pages
  fields:
    foreignkey:
      label: Related Page
      type: multiselect
      min: 1
      max: 1
      options: query
      query:
        fetch: site.find('myRelatedParentPage').childrenAndDrafts
        text: "{{ page.title }}"
        value: "{{ page.autoid }}"
  validate:
    unique: myRelatedPages #<-- use name of your field
...

3.4 The relation fields

There are three equally important fields you need to add to the manytomany field. They specify the template of the related pages, their parent-page and the name of the corresponding manytomany field in their blueprint. Make sure to fill them out correctly.

myRelatedPages:
  type: manytomany
  lable: My Related Pages
  fields:
    foreignkey:
      label: Related Page
      type: multiselect
      min: 1
      max: 1
      options: query
      query:
        fetch: site.find('myRelatedParentPage').childrenAndDrafts
        text: "{{ page.title }}"
        value: "{{ page.autoid }}"
  validate:
    unique: myRelatedPages
  relatedPage: myRelatedFolder #<-- name of the parent-page of the linked pages
  relatationField: myOtherRelatedPages  #<-- name of the corresponding manytomany-field in the blueprint of linked pages
...

3.5 Corresponding blueprint

To be able to edit the relation from both sides, both blueprints of the related pages need to have a field of the type manytomany. They need to have corresponding values in the specific fields. Here is an example of two blueprints, in this case with a relation between students and schools.

school.yml

student.yml

Once your blueprints are setup like this, the manytomany field changes on both sides, when there is an update from one of them.

3.6 Additional structure fields

As mentioned above, the manytomany field is just a structure field with some special fields. That means you can add any number of fields to the structure, if you need to save some extra information about the relation, e.g. a year. Just make sure the two linked blueprints both have the extra fields in the manytomany field:

school.yml

student.yml

3.7 How to use in templates

employee.php

children()->findBy("autoid", $project->foreignkey()->value()); ?>

Title: title() ?>

Hours: hours() ?>

">

Projects

// using the `toStructure()` method, we create a structure collection from the manytomany-field $projects = $page->projects()->toStructure(); // we can then loop through the entries and render the individual fields foreach($projects as $project): // Fetching the project page by using the findBy-method on the parent-page of the related pages $projectPage = page("projects")->children()->findBy("autoid", $project->foreignkey()->value()); ?> <h2>Title: $projectPage->title() ?>h2> <h2>Hours: $project->hours() ?>h2> endforeach; ?>

License

MIT

Credits

Comments
  • Invalid field type (

    Invalid field type ("relation")

    I am using the plainkit with no plugins except "kirby3-autoid" and "kirby3-many-to-many-field" and tested it with the example files you provided. I get the error message Invalid field type ("relation") inside "work" or "artist" subpage. Same problem with the other blueprint examples.

    opened by snau 3
  • Relations to draft pages appears broken

    Relations to draft pages appears broken

    When I attempt to create a relation to a draft page, I get this error:

    Screenshot 2022-03-09 at 12 02 35

    The problem seems to be the use of page() in index.php, which will only return published pages according to the docs:

    "The page() helper fetches published pages only. To fetch a draft, you have to use $kirby->page('somepage')." Source: https://getkirby.com/docs/reference/templates/helpers/page

    The solution seems to be to replace all instances of page() with kirby()->page().

    Posting here instead of a PR just in case there's some side-effect I'm not thinking of.

    Thanks!

    opened by pichiste 1
  • faster lookup

    faster lookup

    instead of using $projectPage = page("projects")->children()->findBy("autoid", $project->foreignkey()->value()); a call to $projectPage = $project->foreignkey()->fromAutoID(); should be a bit faster (but maybe less easy to read).

    https://github.com/bnomei/kirby3-autoid/blob/5a35e31437d8f7bfbfe8da7ac7e2d66fadbe1a78/index.php#L120

    otherwise great plugin!

    opened by bnomei 1
  • Composer doesn't work

    Composer doesn't work

    Hi, if I try to install your plugin with composer it breaks with the following error:

    [InvalidArgumentException]
      Could not find a matching version of package jonasholfeld/kirby3-many-to-many-field. Check the package spelling, your version constraint and that the package is available in a stability which matches your minimum-stability (stable).
    

    Also I couldn't find your project on packagist. So it looks that you have forget to publish the plugin for composer. It would be nice if you could added a working composer install possibility!

    Cheers

    opened by janstieler 1
  • Fixing bug with creating relations to draft pages

    Fixing bug with creating relations to draft pages

    When I attempt to create a relation to a draft page, I get this error:

    Screenshot 2022-03-09 at 12 02 35

    The problem seems to be the use of page() in index.php, which will only return published pages according to the docs:

    "The page() helper fetches published pages only. To fetch a draft, you have to use $kirby->page('somepage')." Source: https://getkirby.com/docs/reference/templates/helpers/page

    The solution seems to be to replace all instances of page() with kirby()->page().

    opened by pichiste 0
  • Sorting Structure leads to unexpected deleting of relations

    Sorting Structure leads to unexpected deleting of relations

    When you sort the structure inside the many-to-many-field via drag'n'drop in the panel, the row-ID gets changed and the plugin doesn't find the corresponding entry in the related page anymore, which leads to faulty deleting the relation only on one side. The bug is fixed in the sortable-structure-bugfix which will be merged into the master as a new version. The bugfix is backwards compatible, you just need to pull the branch (or the master once it's merged) into your kirby plugin folder. I highly recommend doing this as the bug can lead to the loss of data.

    opened by jonasholfeld 1
Releases(v1.0.2)
Owner
Jonas Holfeld
Student at HTWK Leipzig in the field of Media and IT.
Jonas Holfeld
YCOM Impersonate. Login as selected YCOM user 🧙‍♂️in frontend.

YCOM Impersonate Login as selected YCOM user in frontend. Features: Backend users with admin rights or YCOM[] rights, can be automatically logged in v

Friends Of REDAXO 17 Sep 12, 2022
A Magento 2 module that allows for creating discrete PDP (Product Detail Pages) page layouts for customers landing on the site from a PPC (Pay Per Click) link/ad by allowing routing to the same pages using a `/ppc/` prefix in the URL path.

A Magento 2 module that allows for creating discrete PDP (Product Detail Pages) page layouts for customers landing on the site from a PPC (Pay Per Click) link/ad by allowing routing to the same pages using a `/ppc/` prefix in the URL path.

null 16 Nov 11, 2022
Perch Dashboard app for exporting content to (Kirby) text files and Kirby Blueprint files

toKirby Perch Dashboard app for exporting content to (Kirby) text files and Kirby Blueprint files. You can easily install and test it in a few steps.

R. Banus 4 Jan 15, 2022
Plugin for Kirby that allows you to load assets generated by Vite.

Kirby Vite Plugin Plugin for Kirby that allows you to load assets generated by Vite. In development mode, assets are loaded from Vite's development se

Oblik Studio 10 Nov 20, 2022
Greyhole uses Samba to create a storage pool of all your available hard drives, and allows you to create redundant copies of the files you store.

Greyhole Greyhole is an application that uses Samba to create a storage pool of all your available hard drives (whatever their size, however they're c

Guillaume Boudreau 245 Dec 18, 2022
This composer plugin allows you to share your selected packages between your projects by creating symlinks

Composer - Shared Package Plugin This composer plugin allows you to share your selected packages between your projects by creating symlinks. All share

L'Etudiant 169 Sep 20, 2022
Prisma is an app that strengthens the relationship between people with memory loss and the people close to them

Prisma is an app that strengthens the relationship between people with memory loss and the people close to them. It does this by providing a living, collaborative digital photo album that can be populated with content of interest to these people.

Soulcenter 45 Dec 8, 2021
Run your WP site on github pages, php innovation award winner https://www.phpclasses.org/package/12091-PHP-Make-a-WordPress-site-run-on-GitHub-pages.html

Gitpress Run wordpress directly on github pages Gitpress won the innovation award for may 2021 Read more about this https://naveen17797.github.io/gitp

naveen 13 Nov 18, 2022
A fully-managed real-time messaging service that allows you to send and receive messages between independent applications.

A fully-managed real-time messaging service that allows you to send and receive messages between independent applications.

Google APIs 58 Dec 23, 2022
Envbar allows you to differentiate between environments by adding a custom colored bar above the top navigation.

Envbar Envbar allows you to differentiate between environments by adding a custom colored bar above the top navigation. This should help backend users

Magenizr 6 Oct 7, 2022
A Magento 2 module that allows admins to duplicate CMS blocks and pages from their respective grids and en masse.

element119 | CMS Duplicator ?? Features ✔️ Allows merchants to duplicate CMS blocks and pages from the Action column in the admin grid ✔️ Allows merch

Kiel Pykett 13 Oct 13, 2022
A useful PocketMine-MP plugin that allows you to create crates in-game!

ComplexCrates A useful PocketMine-MP plugin that allows you to create crates in-game! Commands Main command: /crate Sub commands: create

Oğuzhan 8 Aug 26, 2021
WooCommerce Empty Cart Button plugin helps you to add Empty Cart button to WooCommerce Pages/Sections using Shortcode only.

WooCommerce Empty Cart Button plugin helps you to add Empty Cart button to WooCommerce Pages/Sections using Shortcode only. How to use? Download the p

Katr 2 Sep 24, 2022
Magento 2 Preview/Visit Catalog allows the store owner to quickly preview the catalog (product & category) pages from the admin panel.

Magento 2 Preview/Visit Catalog Overview Magento 2 Preview/Visit Catalog allows the store owner to quickly preview the catalog (product & category) pa

Raj KB 4 Sep 27, 2022
Kirby plugin to visually show hidden characters in all kind of input fields and their previews.

Kirby Hidden Characters Kirby plugin to visually show hidden characters in all kind of input fields and their previews. This includes white spaces and

Jakob Grommas 21 Oct 17, 2022
Coder Metabox for WordPress - Create Pages, Posts Custom Meta Fields options

Coder Metabox for WordPress Coder Metabox for WordPress - Create Pages, Posts Custom Meta Fields options. Step 1 call coder-metabox.php file in functi

Ashikur Rahman 3 Feb 19, 2022
Create eye-catching Open Graph images for each (or some) site pages

Open Graph Image Generator for Laravel Create Open Graph images (og:image, twitter:image, vk:image) for each (or some) site pages. Use page title to c

Pavel Bychko 4 Nov 11, 2022
Silverstripe module allowing editors to create newsletters using elemental blocks and export them to a sendy instance

Silverstripe Sendy Silverstripe module allowing editors to create newsletters using elemental blocks and export them to a sendy instance. Introduction

Syntro Opensource 4 Apr 20, 2022