Relations

Case study

For the purpose of the documentation, the database structure of our basic component "Hello My World" is the following :

database helloworld 1

From this digram we can determine the following relations :

  • A continent Has Many countries (N:1)
  • A country Has One continent (1:N)
  • A country Has Many cities (N:1)
  • A city Has One country (1:N)
  • A city Has Many visits (N:1)
  • A city Belongs To Many travellers (N:m)
  • A traveller Has Many visits (N:1)
  • A traveller Belongs To Many cities (N:m)

Visits is the pivot table between travellers & cities :

  • A vist Has One city (1:N)
  • A visit Has One traveller (1:N)

The naming conventions are inspired from the FOF conventions.



One to Many - 1:NCook Joomla! Relation 1n Foreign Key

First level

From a city, you can load its unique parent country. Let's load country.name
In the fields tree, just drag the 'Name' sub node from the 'Country' node:

Simple Foreign Key

Infinite levels

From a city, you can load its unique parent continent. Let's load country.continent.name
In the fields tree, just drag the 'Name' sub node from the 'Continent' node:

Infinite relations

Forms

Especially in forms, it makes no sense to load a second level Foreign Key. You can only drag the first level node because, in our case, a continent can have many countries, so the city cannot attach to a continent directly. Instead, you can group the countries list by its continent. (see the field properties, once instancied)
Fallback: In case you try to drag an incoherent node to the form, it will automatically be reduced and the default field of the table will be used instead.



Many to One (N:1)Cook Joomla! Relation N1 Many-To-One

At the end of the fields tree of a table, are listed all relations to it. (Also called cross references.)
In our case, let's load all cities from a country:
The cross-reference table is the Foreign Table.

Relation Many to One



Many to Many (N:m)image relation nm

Depending the node you drag, Cook will automatically determines if it refers to a N:1, or to a N:m
In our case, let's load all the travellers who visited the given city.

Relations Many to Many

In this example, the XREF node becomes the Pivot Table.

Model behaviors kept

Items are automatically managed in the pivot table. Creation and destruction of the links are handled by the pivot model.
It means that all the behaviours of that model will work when the N:m links are managed.
ex: If you have a 'creation_date' field + its wizard, in the pivot table (visit), then the date will be populated with the link creation.
Do you understand what I mean... Well I hope I explained it well.

Raw mode (optimization model-less)

So, regarding to the previous point, if you do not have particular treatments in that pivot model, you can optimize the queries, using the 'raw' mode in the relation declaration:

$this->belongsToMany('travellers',
    null,
    'id',
    'id',
    'visits',
    'city',
    'traveller',
    array('name'),

// HERE                     
    true // Raw mode 
);



Integrities

The children items can be automatically suppressed when their parent are lost.
This feature is managed separately, it depends how your component is built.

In case of N:m, the integrities are important because the links created in the pivot table are dependant of their parents.

learn more : Integrities



Forms

Both N:1 and N:m will display a mutiple selection list, rendered with chosen library:

Relations Multiple list

The only difference stands for N:1. Only the availables values are listed.
In the following example (country Has Many cities), you can see 'Bruxells, Paris' because they are not been linked to any country at the moment.
The selected values appears disabled.

Relations multiple select list



One to One (1:1)image relation 11

One to One is used to extends a table.
Cook does not handle this at the moment. More patience...



Filters

Cross-reference filters are not handled at the moment.



Understanding the code.

Declaration

A relation is defined in the plural model constructor as follow:


In Countries 

$this->hasMany('cities', // name
    null, // foreignModelClass
    'id', // localKey
    'country', // foreignKey,
    array('name') // selectFields
);

relations definition many to one

  • When foreignModelClass is null, the 'name' property is used.
  • selectFields contains all the fields to load in the query.

In Cities 

$this->belongsToMany('travellers', // name
    null, // foreignModelClass
    'id', // localKey
    'id', // foreignKey,
    'visits', // pivotModelClass,
    'city', // pivotLocalKey
    'traveller', // pivotForeignKey
    array('name') // selectFields
);

relations terms nm

Loading

At any moment you can load the cross-reference lists (N:1, or N:m)
In our example, let's load the cities of a country:

 

$countryModel->loadRelations('cities');

 

It works as well for the lists:

 

$countriesModel->loadRelations('cities'); 



Infinite cross-references

Your generated component can handle infinite level of cross-lists (in an pretty good optimized way).
But... The builder interface is not ready yet, so you have to code it by hand.

1. Model
Be sure that all the requested relations are defined in the plural model constructor.
Add the fields you want in the selectFields param.

2. View
Load the lists:

$model->loadRelations('cities.travellers');

3. Template
Create a template file to display the datas. We highly recommend you to create headless layouts in the 'layouts' folder of your component.
learn more : Layouts

Get Started