So just to be totally clear, as Hannes mentions in his last line, subforms are ideal for inputting data for a many-to-many link table. What you need to do is write the data out to the link table, not to a field in a table as a json.
For example suppose you have a database containing a table for books, a table for authors, and a link table bookauthor to enable a many to many relationship (a book may have several authors, an author may contribute to several books)
In the book edit form you want to be able to assign authors to the book.
So create a subform named authorlist in the book edit form which enables selection of multiple names from the authors table and returns the selected ids.
<field name= "authorlist"
type= "subform"
label= "Authors"
description="Select authors for this book"
min= "0"
max= "10"
formsource= "administrator/components/com_yourcomponent/models/forms/peoplelist.xml"
multiple= "true"
buttons= "add,remove,move"
layout="joomla.form.field.subform.repeatable-table"
groupByFieldset="false"
/>
The formsource for the author list might be a simple sql field getting the names (AS text) and ids (AS value) for the list, or it might be a custom field.
In the model for book edit create (or add to) the loadFormData() function like this:
protected function loadFormData() {
$data = Factory::getApplication()->getUserState('com_yourcomponent.edit.book.data', array() );
if (empty($data)) {
$data = $this->getItem();
$data->authorlist=$this->getBookAuthorlist();
}
return $data;
}
function getBookAuthorlist() {
$db = $this->getDbo();
$query = $db->getQuery(true);
$query->select('
a.id as author_id');
$query->from('#__bookauthorAS ba');
$query->innerjoin('#__authors AS a ON ba.author_id =
a.id');
$query->where('ba.book_id = '.(int) $this->getItem()->id);
$query->order('ba.listorder ASC');
$db->setQuery($query);
return $db->loadAssocList();
}
This will load any existing authors into the subform if you are editing an existing item.
Then in the model save($data) function you simply need to update the link table once the parent::save($data) function has returned ok.
The quirk here is that since authors may have been deleted as well as added during the edit you need to start by deleting all of the existing authors for the book in the bookperson table and then add back all of the selected ones.
$book_id = $this->getState('
book.id');
$personList=$data['authorlist'];
$db = $this->getDbo();
//delete any existing entries for this book
$query = $db->getQuery(true);
$query->delete($db->quoteName('#__bookauthor'));
$query->where('book_id = '.$book_id);
$db->setQuery($query);
$db->execute();
//restore the new list
foreach ($personList as $pers) {
$query = $db->getQuery(true);
$query->insert($db->quoteName('#__bookauthor'));
$query->columns('book_id, person_id, listorder');
$query->values('"'.$book_id.'","'.$pers['person_id'].'","'.$pers['order'].'"');
$db->setQuery($query);
$db->execute();
$order++
}
NB I am also including an 'listorder' column in the link table so that authors for a book can be listed in a specific order - sometimes the lead author needs to be listed first. The subform with move button will generate an order field.
It is all quite simple once you try it. Of course for user convenience you will want to have a corresponding subform on the author edit page to assign an author to a book, otherwise you have to remember to create the author entry before you edit the book and vice versa!
Hope this helps (and hope it is right!!)
RogerCO