All Projects → jonasholfeld → kirby3-many-to-many-field

jonasholfeld / kirby3-many-to-many-field

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

Programming Languages

PHP
23972 projects - #3 most used programming language
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to kirby3-many-to-many-field

kirby-minify-html
Enable minify HTML output for Kirby 3
Stars: ✭ 27 (-28.95%)
Mutual labels:  kirby, kirby-cms, kirby-plugin, kirby3
laravel-mix-kirby
Laravel Mix helper for Kirby
Stars: ✭ 23 (-39.47%)
Mutual labels:  kirby, kirby-cms, kirby-plugin, kirby3
kirby-membership
Simple Membership plugin for Kirby CMS
Stars: ✭ 27 (-28.95%)
Mutual labels:  kirby, kirby-cms, kirby-plugin
kirby-html-minifier
Minify the html output of a site built with Kirby CMS
Stars: ✭ 20 (-47.37%)
Mutual labels:  kirby-cms, kirby-plugin, kirby-3
vuekit
Kirby 3 + Vue.js kit
Stars: ✭ 16 (-57.89%)
Mutual labels:  kirby, kirby-cms, kirby3
kirby-highlight
Themeable server-side syntax highlighting for Kirby
Stars: ✭ 14 (-63.16%)
Mutual labels:  kirby, kirby-cms, kirby-plugin
kirby-git
Kirby plugin for updating content in the panel via Git
Stars: ✭ 75 (+97.37%)
Mutual labels:  kirby, kirby-cms, kirby-3
retour-for-kirby
Kirby 3 plugin to manage redirects and track 404s right from the Panel
Stars: ✭ 96 (+152.63%)
Mutual labels:  kirby, kirby-cms, kirby-plugin
kirby-podcast
A KirbyCMS-Podcast-Plugin
Stars: ✭ 22 (-42.11%)
Mutual labels:  kirby, kirby-cms, kirby-plugin
search-for-kirby
Kirby 3 plugin for adding a search index (sqlite or Algolia).
Stars: ✭ 42 (+10.53%)
Mutual labels:  kirby, kirby-cms, kirby-plugin
kirby-blade
Enable Laravel Blade Template Engine for Kirby 3
Stars: ✭ 20 (-47.37%)
Mutual labels:  kirby, kirby-cms, kirby-plugin
field-engineer
A Kirby field for complex field structures.
Stars: ✭ 49 (+28.95%)
Mutual labels:  kirby, kirby-cms, kirby-plugin
kirbyup
🆙 Zero-config bundler for Kirby Panel plugins
Stars: ✭ 33 (-13.16%)
Mutual labels:  kirby, kirby-cms, kirby-plugin
kirby-ga
Kirby GA - Google Analytics
Stars: ✭ 16 (-57.89%)
Mutual labels:  kirby, kirby-cms, kirby-3
kirby-securedpages
Protect pages for authenticated users
Stars: ✭ 28 (-26.32%)
Mutual labels:  kirby-cms, kirby-plugin, kirby3
kirby-boiler-field
Boilerplate for Kirby form fields
Stars: ✭ 15 (-60.53%)
Mutual labels:  kirby, kirby-cms, kirby-plugin
monochrome
A fully responsive Kirby CMS theme
Stars: ✭ 27 (-28.95%)
Mutual labels:  kirby, kirby-cms
kirby-blade
Enable Blade for Kirby 3
Stars: ✭ 14 (-63.16%)
Mutual labels:  kirby, kirby-3
kirby-blade-template
⬢ Laravel Blade template component for Kirby CMS.
Stars: ✭ 26 (-31.58%)
Mutual labels:  kirby-cms, kirby-plugin
hfg-documentation-generator
The HfG Documentation Generator
Stars: ✭ 13 (-65.79%)
Mutual labels:  kirby, kirby-cms

Kirby 3 Many To Many Field

⚠️ Please update to v1.0.2 if you used the plugin before, as the old version contained a bug that could lead to data loss. See the issue Sorting Structure for more info on the bug. ⚠️

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

title: School
fields: 
  students:
    type: manytomany
    label: Students
    fields:
      foreignkey:
        label: Student
        type: multiselect
        min: 1
        max: 1
        options: query
        query:
          fetch: site.find('students').childrenAndDrafts
          text: "{{ page.title }}"
          value: "{{ page.autoid }}"
    validate:
      unique: students
    relatedPage: students
    relatationField: schools
  autoid:
    type: hidden
    translate: false  

student.yml

title: School
fields: 
  students:
    type: manytomany
    label: Students
    fields:
      foreignkey:
        label: Student
        type: multiselect
        min: 1
        max: 1
        options: query
        query:
          fetch: site.find('students').childrenAndDrafts
          text: "{{ page.title }}"
          value: "{{ page.autoid }}"
      year:
        type: number
    validate:
      unique: students
    relatedPage: students
    relatationField: schools
  autoid:
    type: hidden
    translate: false 

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

title: School
fields: 
  students:
    type: manytomany
    label: Students
    fields:
      foreignkey:
        label: Student
        type: multiselect
        min: 1
        max: 1
        options: query
        query:
          fetch: site.find('students').childrenAndDrafts
          text: "{{ page.title }}"
          value: "{{ page.autoid }}"
      year: #<-- some extra field
        type: number
    validate:
      unique: students
    relatedPage: students
    relatationField: schools
  autoid:
    type: hidden
    translate: false 

student.yml

title: Student
fields: 
  schools:
    type: manytomany
    label: Schools
    fields:
      foreignkey:
        label: School
        type: multiselect
        min: 1
        max: 1
        options: query
        query:
          fetch: site.find('schools').childrenAndDrafts
          text: "{{ page.title }}"
          value: "{{ page.autoid }}"
      year: #<-- the same extra field
        type: number    
    validate:
      unique: schools
    relatedPage: schools
    relatationField: students
  autoid:
    type: hidden
    translate: false  

3.7 How to use in templates

employee.php

<h1>Projects</h1>
<?php
// 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 fromAutoID-fieldMethod from the AUTOID plugin
    $projectPage = $project->foreignkey()->fromAutoID(); ?>
    <!-- Getting the title from the related page  -->
    <h2>Title: <?= $projectPage->title() ?></h2>
    <!-- Getting the hours from the structure entrie -->
    <h2>Hours: <?= $project->hours() ?></h2>
<?php endforeach; ?>

License

MIT

Credits

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].