J3.x

J3.x:Developing an MVC Component/Adding Associations

From Joomla! Documentation

Revision as of 15:36, 4 July 2018 by Robbiej (talk | contribs) (Page created)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Joomla! 
3.x
Tutorial
Developing an MVC Component



This is a multiple-article series of tutorials on how to develop a Model-View-Controller Component for Joomla! VersionJoomla 3.x.

Begin with the Introduction, and navigate the articles in this series by using the navigation button at the bottom or the box to the right (the Articles in this series).



This tutorial is part of the Developing an MVC Component for Joomla! 3.2 tutorial. You are encouraged to read the previous parts of the tutorial before reading this.

In this step we add multilingual associations.

Under Construction!

Introduction

In this step we enhance our component to support multilingual associations, which enable us to associate an item in one language with its equivalent in another language. This functionality is useful in a number of respects:

  • Primarily it assists administrators of a multilingual site in maintenance of the data across the different languages. From a practical data management perspective, it's essential to have some mechanism for keeping track of which items are the equivalents of others in different languages, and implementing Joomla associations on your component means that administrators can use the same processes as they would for other Joomla items such as articles, menus and contacts.
  • On the front end a user can click on the symbol within the language switcher to go to the equivalent item in another language.Â
  • In the html header Joomla outputs links to the equivalent items in other languages using the hreflang attribute. This enables search engines to find these equivalents, which they then use to try to deliver more pertinent search results to users.
  • Translators can use the Joomla Multilingual Associations component to display in a side-by-side view the item in the reference language and its equivalent in the target language, thus aiding the process of translation.

The development of this functionality will involve using some of the APIs around the Joomla form class JForm.

Functionality

We enhance our helloworld component to support associations for both helloworld records (items) and helloworld categories.

On the back end we allow administrators to set associations as part of editing helloworld items or categories, and extend the list view to display the defined associations. We also enable the use of the Joomla Multilingual Associations component.

On the front end we provide the ability for users to switch to the associated helloworld item or category whenever they click on a flag symbol within the language switcher. And we ensure that the hreflang links in the html head element are set correctly.

Approach

Database Access

Associations are stored in the Joomla associations table, which has 3 fields

  • context - the type of record to which this association refers, eg com_menus.item, or com_content.category
  • id - the id of the record to which the association refers, eg the menuitem id, or article category id
  • key - a field which allows Joomla to find the other records which are associated with this one, because they all have the same key. (Joomla takes an array of the ids + context of the records which are associated together, JSON-encodes this to form a string, and takes an MD5 hash of the string to form the value of the key which is then stored in each of those records).

Joomla provides a function JLanguageAssociations::getAssociations which enables components to find associated records. You pass it the context and id of your record, and it then finds records in the associations table which have the same key as yours, passing back the results in the form of an associative array, keyed by the language tag. As we will see, it will also return additional information about the resultant records, such as the alias and category id, provided we tell it where we store that data, so that it can add the appropriate SQL JOIN clauses.

Code for updating and deleting the association records is in the JModelAdmin class, which our own administrator helloworld model inherits from, and to reuse this we just need to specify the context we're using for our associations.

Helloworlds Display

We'll add another column in our display for the associations. After obtaining the associations as described above we'll use a standard layout file used by Joomla core components for displaying the associations. Following the example of other components, we'll put all this code into our helloworlds layout file, even though with an MVC implementation obtaining the associations details would usually fit within the remit of the model.

Helloworld Edit

In line with other Joomla components we add in our edit.php layout file another bootstrap tab where the administrator can set the associations. On this tab we'll put fields to select an association for each of the other contact languages on our system, but because we don't know how many other languages will be installed we have to add these fields dynamically (in our model) using the JForm APIs, rather than specifying them in an XML file.

When the administrator presses the select button to select the associated record we'll show a modal displaying the helloworld records, just as we did in the previous tutorial step when defining a menuitem, and we'll reuse the modal field definition code which we developed there. However in this case, when the modal is shown, we want to restrict the records displayed to only those with the correct language, and to enable this we use an extra parameter forcedLanguage, which is set to the tag of the content language in question.

As usual, when editing records we need to prefill the form with any existing associations.

Finally, in our model we define the associations context so that the JModelAdmin code can handle looking after the database updates of the associations records.

Enabling the Multilingual Associations component

First of all we need to provide some configuration data (as described HERE) to enable the Multilingual Associations component work with our helloworld component. We also need to define a couple of language strings for the drop-down selection box for choosing which record types to work with.

Once the user selects the type of record, the reference and target records can be displayed side-by-side in 2 iframes. In our case the URL for the iframes will be similar to when the administrator clicks on a record in the helloworlds view, namely passing the id of the record with task=helloworld.edit. So we will be reusing our MVC code for editing a helloworld record, but some changes will be necessary to generate the display we need.

Linking to associated records on the front end

When Joomla is generating the hreflang and language switcher links for our helloworld component on the front end it looks for a class HelloworldAssociationHelper in a helper file association.php, and tries to call a getAssociation method of that class, and this is what we have to code. Joomla passes in the view and record id, and we return the id of the associated helloworld record or category.

Enabling Associations for helloworld categories

Joomla comes with all the code to support associations for our helloworld categories. It checks if there's a class ContentAssociationsHelper in administrator/components/com_content/helpers/associations.php and if so then enables the functionality to support associations on the helloworld categories. Our front end helper file association.php is also necessary, to return the appropriate category association when requested.

Other consequential changes

We're now using our Helloworlds view in 3 different contexts

  1. Displaying a table of our helloworld records when the administrator clicks on Components / Hello World - functionality developed some time ago
  1. Displaying the helloworld records in a modal when the administrator is defining a site menuitem pointing at a helloworld record, and needs to choose the record to be shown - functionality developed in the previous step, Adding a Modal
  1. Displaying the language-specific records in a modal to allow the administrator to select the associated helloworld record - functionality from this step.

With each of these we're displaying the filter/search fields at the top of the form, and as described in the step Adding Pagination, whenever an administrator selects eg a filter in one of these fields the information is stored in the user session, so that when the form is redisplayed the same filter is applied. The problem is that currently this information is stored in the same place for all 3 contexts, so for example, if the administrator is choosing a French record for an association, and then clicks on Components / Hello World, then it will show just the French records in the table.

To fix this in our helloworlds model we need to determine which context it is, and set the $context variable differently, as it's this JModelAdmin protected variable which acts as a key for this session information. (Note that this context has nothing to do with the context field in the associations table.)

As well as that, we'll need to make some changes to our helloworld custom router.


Contributors