Coding a N:M relation


Please use the Relations instead.


Download and install the sample component : 

Version : 1.1

This tutorial can be read in 3 different ways :

  1. Read and understand the furnished fork. (duration : 1h)
  2. Try to re-create the fork from scratch, with the furnished component. (duration : 1h)
  3. Try to rebuild it all in a new component in the builder, and apply your forks on it. (duration : 1h)

Help : more informations about forks.


All forked files are in back-end. It makes it simplier for the tutorial, and also for the tests.

Study of Case : Travellers VISIT Cities

The N:M is linking 2 Lists:

  • Travellers
  • Cities


The cross-reference (Xref) table is created to represent "a visit"
One ore more traveller "Has visited" one ore more cities


Try to reproduce the best you can the component layouts and pages. If you does not configure exactly the same it is not important. You can use modal boxes or not, you can add some more fields types (recommended) because it will help you to make some tests, and try some more possibilities.

IMPORTANT : The following configuration is really important for making the feature working :

Cascad integrity delete

When a City or a Traveller is deleted, all the reffered links must disappears. (most cases)

For every fk in the Xref table, choose 'FK integrity' = 'cascad' in the field properties.

N:M Foreign Key Integrity Cook

Prepare the models

(This steps will be generated by Cook in future)
Before to be able to call N:M lists easily, you need to prepare all the concerned models.

Step 1 : Create optimized profiles in the Xref model.

Those profiles will load the most minimalist datas, for improving performances. 

    a. Fork visits (list) model


    b. Fork prepareQuery()  : create 3 SQL profiles.

    You are free to define the profiles you want. The 'object.' prefix is arbitary choosen.
    We will reuse those profiles all along the tutorial to populate others objects (they are not called by the main view/template of its own triad)

    • object.default : is loading both sides
    • object.cities : is loading only cities names, when a traveller is defined, we do not need to load the travellers join.
    • object.travellers : is loading travellers names, when a city is defined, we do not need to load the cities join.


    Help : more informations about prepareQueryHeaders()


    Step 2 : Auto-populate $cities in traveller

    a. Fork the traveller (item) model


    b. Create populateObjects()

    Help : more informations about loadXref().

    This will open the possibility to load the cross-reference list from an item, simply using state var (xref.cities)

    Dump object traveller N:M cities

    The traveller item contains now a new array property ($cities), not physically in the database table, containing the Xref list.
    This array can contains unlimited cascad mixed objects.

    Step 3 : Auto-populate $travellers in city

    Same than previous, but oposite way

    a. Fork the city (item) model


    b. Create populateObjects()

    Step 4 : Repeat steps 2 & 3 in the list models

    a. Fork the travellers (list) model


    b. Fork the cities (list) model


    Objective 1 : Show the cross-reference list in a fly

    The goal is to show a list of travellers in a city fly.

    Cross reference Cook N:M

    Step 1 : Ask to the model to load the travellers when loading this layout.

    This layout is loaded in modal in our component sample.

    a. Fork the city (item) view


    b. Fork displayVisits()

    Ask to the model to populate the travellers.

    Step 2 : Display this list of travellers in the city fly layout.

    In the sample component, the layout is called 'visits' and can load in modal (more convenient)

    a. Fork the fly template file:


    Objective 2 : Create a multi-select input in form.

    Choosing cities from a traveller will create the links.

    N:M Cook Input multi select joomla form

    Step 1 : Prepare the model to save the recieved list of values to the N:M

    This code is required in the item model after saving the item.
    In our example, we will prepare only for traveller.

    a. Fork traveller (item) model


    b. Fork save() function 


    Help : more informations about updateXref().


    Step 2 : Use JForms to instance the input

    Use xref input type (since 2.6.3)

    a. Fork the XML form file:


    b. Empty the file and leave only the necessary in the fork:

    Help : more informations about xref field.

    Step 3 : Configure the view for sending the datas to the input

    a. Fork the traveller (item) view:


    • ask the xref objects
    • pass the list to a temporary array ($lists)

    b. Fork the traveller (item) form template:


    Pass the dynamic list to JDom

    Objective 3 : Embed a list within a list

    Visited cities are added as a new column row

    Cook embed lists Joomla

    Step 1 : Ask the population of cities

    a. Fork the travellers (list) view:


    b. Fork displayDefault():

    Step 2 : Render cities in the grid

    a. Fork the grid template:


    b. Add a table column (header + rows):

    Objective 4 : Create N:1 (inversed Foreign Key)

    This example does not permit to create countries 'on the fly'.

    A country must be free of continent (FK) to appear in the list.

    N:1 Cook Joomla

    Step 1 : Prepare the model for creating optimized list

    a. Fork countries (list) model:


    b. Create a custom profile: object.default

    Step 2 : Prepare the item model

    a. Fork continent (item) model:


    b. Auto-populate $countries in continent

    c. Fork the save() function for recieving post array :

    Step 3 : Load list of availables items

    In case of N:1, the items already linked are not selectable. Even if the link is broken.

    a. Prepare the continent (item) view


    • Ask the xref objects
    • VERY IMPORTANT : filter the list of countries for only those allowed to select.
    • Pass the list to a temporary array ($lists)

    b. Fork the continent form template


    Step 4 : N:1 Form

    a. Fork the continent XML form


    b. Instance the xref input:

    Step 6 : Reproduce it for defining cities within the country form.

    Facultative exercice :

    Repeat the previous steps 1 to 4 to do the same in the city form :

    1. Optimized list in cities : prepareQuery()
    2. Country model get / set cities : populateObjects() + save())
    3. View / Template : pass objects : displayCountry() + country_fly.php
    4. XML form : xref input

    The result looks like this:

    N:1 Cities

    Objective 5 : Mixed objects and multi-level

    The goal is to load all availables datas from the continents list.
    Each item is editable in modal, containing all the previously realized forks.

    N:M mixed objects Cook Joomla Foreign keys

    Step 1 : Preparation : propagate states with followers in each concerned model.

    This definition of children states allows you to automatically follow the xref states to their children lists in cascad.

    a. open the forked continents (list) models


    b. Add states followers in populateObjects()

    c. Repeat the operation for countries (item) model


    Step 2 : Ask to load the cross referenced objects in the view

    a. Fork the continents view file


    b. Ask to the loader to populate all the following xref lists:

    • Countries (xref.countries)
    • Cities (xref.countries.cities)
    • Travellers (xref.countries.cities.travellers)

    Step 3 : Build the template with the availables datas.

    The template stucture will not be explained in this tutorial.
    If you are recreating the fork from scratch, just dump the items, and observe the mixed object tree.

    Dump the list to see all tree:

    echo("<pre>"); print_r($this->items); echo("</pre>");

    Cook mixed Foreign Keys Cross reference

    You can now build yout template as you want.

    Have fun ;-)

    Get Started