J1.5

Difference between revisions of "Component parameters"

From Joomla! Documentation

m (→‎With overrides: The 'merge' example needs to convert the raw table 'params' column to a compatible JParameter/JRegistry first.)
Line 241: Line 241:
 
<source lang="php">
 
<source lang="php">
 
<?php
 
<?php
   $params->merge( &$row->params );
+
   $params->merge( new JParameter( &$row->params ) );
 
?>
 
?>
 
</source>
 
</source>

Revision as of 22:50, 6 September 2009

The "J1.5" namespace is an archived namespace. This page contains information for a Joomla! version which is no longer supported. It exists only as a historical reference, it will not be improved and its content may be incomplete and/or contain broken links.

Background[edit]

One thing that sets Joomla! Components apart from other types of Extension (i.e. Modules and Plugins) is the ability to store significant quantities of data in the Joomla! MySQL database. Typically, this data will be content for displaying on a page (such as the content of an article, or its title) or data about how that content should be displayed (e.g. a setting specifying whether or not the title should be shown). A Component normally creates at least one table in the database to store this data - for example, data for articles associated with the com_content Component are stored in the jos_content table (where jos is the table prefix for the site).

However, choosing exactly how to store each item of data requires a little more thought. There are essentially two choices: each data item may be stored in its own field, or a collection of data items may be stored within a single parameters field. (Of course, there is nothing to stop you making use of both methods, for different data items, within the same component). Which approach you use for a given data item is largely a matter of personal choice, although there are some factors to consider:

  • Core code included in the Joomla! installation makes it very easy to produce the appropriate form elements for entering data into parameters in the Back-end. If you choose to save the data in separate fields, you will need to code the appropriate form elements yourself.
  • Again, Joomla! core code allows you to set default values for parameters across the whole component. Individual component items (e.g. individual articles) can then choose to use the default values, or to override them with values specific to that item. See below for details of how to do this.
  • It is not possible to extract individual parameter values directly from the database. Instead, the whole parameters field must be extracted and parsed to obtain the different parameter values. This means that it is not very easy, for example, to run MySQL queries that search for a parameter with a particular value. Any data that you want to run queries against should be given its own table field.
  • Similarly, it is not possible to run data validation on parameter fields before saving data.

In general, parameters are conventionally used to store data relating to the presentation of information. The information itself is generally stored in separate fields.

Types of Component parameter[edit]

1. Component-wide default parameters[edit]

These parameters are set once for the whole Component, and are generally used to provide the 'default' parameter settings for the Component on that particular site.

2. Menu item specific parameters[edit]

A menu link to an individual Component item (e.g. an article) can also have parameters associated with it, which can affect the way the Component item is displayed using that link. The types of parameters available will depend on the way that the Component item is displayed (the 'view' in MVC terms, but don't worry if this doesn't mean anything to you!). However, the precise values of those parameters can be set for each menu link individually. If there is another menu link to that same Component item, then it is important to realise each menu link may have different parameter values, and so the same article may be displayed differently in the two cases.

A menu link can also override the Component-wide default parameters, so that the override values (if set) are used in place of the default values for that Component item when accessed via that menu link. As you would expect, when no override value is set, the default value is used instead, in the normal manner.

3. 'Article' specific parameters[edit]

Finally, each Component item (e.g. article) can have parameters which apply to that item, regardless of how it is accessed (i.e. via any available menu link, or even without reference to a menu at all!). If the Component designer wants, the article specific parameters can also be set up to use the 'override' behaviour, so that they default to the current values of the corresponding Component-wide parameters, though this is not essential. Again, this is described further below.

Storing the parameters and their values.[edit]

In general, a set of parameters is stored within the database in a single text field. Different parameters are separated by newline characters ('\n' in MySQL - each parameter will appear on a different line when you look at the data in something like phpMyAdmin). Each parameter consists of the parameter name and value, separated by an equals sign (=). As an example:

parameter1=parameter1value
parameter2=
parameter3=parameter3value
parameter4=parameter4value

Here, parameter1, parameter3, and parameter4 have all been assigned values, whilst parameter2 has no value. Typically, a parameter will be given no value where it is set up to allow override of a default value, but 'no override is required' - i.e. it is desired to use the default value.

1. Component-wide default parameters[edit]

These are stored in the params field of the jos_components table, in the row corresponding to the particular component to which they apply.

2. Menu item specific parameters[edit]

These are stored in the params field of the jos_menu table, in the row corresponding to the particular menu item to which they apply.

3. 'Article' specific parameters[edit]

These are stored in a text field in the table created by the Component. Whilst there is no strict rule for naming the field, it is common to extend the above pattern using the params name. However, com_content stores article parameters in a field called attribs.

Accessing the parameters - Back-end[edit]

Joomla! includes some shortcuts to enable component creators to easily add parameter forms to the Back-end of their component. These forms allow a site administrator to enter a parameter value by, for example, entering some text in a box, choosing from a drop-down list, or selecting a radio button. To create these forms, each parameter needs to have an associated <param /> object in an XML file. The type of <param /> object determines the form elements that will be shown in the Back-end. A list of the available form elements is given here. More information is given below about the XML file names, structure and location required for each set of parameters.

1. Component-wide default parameters[edit]

These can be created at installation of the Component, by including <param /> elements in the installation XML file (typically called COMPONENT_NAME.xml, and located in the root folder of the Component package. As far as the parameters are concerned, this XML file has the following structure:

<install>
  ...
  <params>
    <param />
    
    <!-- Example: the following will create a line in the parameters field 
    reading 'font_size=16\n': -->
    <param name="font_size" default="16" />
    
    ...
  </params>
  ...
</install>

Each <param /> element must be given the attributes name and default, which define the parameter name and value respectively. These values are then copied to the jos_components table in the database.

However, on its own this is not very useful, as it doesn't allow users to change the values of the parameters. To do this, parameter form elements need to be defined in a file named config.xml which is located in /PATH_TO_JOOMLA/administrator/components/com_COMPONENT_NAME/. The file should have the following structure:

<root>
  <params>
    <url addpath="/administrator/components/com_COMPONENT_NAME/elements">
      <param name="cid" type="JELEMENT_TYPE_NAME" scope="com_COMPONENT_NAME" default="0" label="LABEL" description="DESCRIPTION" />
    </url>
    <param type="type" name="name" description="description" />
    
    <!-- Example: the following will produce a text box 3 characters wide with the label 'Font size:'.  
    When the user hovers the mouse over the label, a tooltip will pop up which states 'Please enter the 
    required font size'.  On saving, a value entered into the text box will be saved as the 'font_size' 
    parameter value. -->
    
    <param type="text" name="font_size" size="3" label="Font size:" description="Please enter the required font size" />
    
    ...
  </params>
</root>

Note that the <root> element can have any name you wish, but there must be one element at the root of the document (this is a requirement for a well-formed XML document). You can have more than one <params> element, but only the first one will be considered. It is not currently possible to group certain parameter form elements together.

The url parameter specifies a parameter which is added to the URL of the menu item. To enable this functionality, you must create a new class which extends JElement and put it in the administrator/components/com_COMPONENT_NAME directory. More information here: http://forum.joomla.org/viewtopic.php?f=476&t=206062.

So that administrators to access these parameters, you will need to add a button to the toolbar in the Back-end of your component. This can be done using the code:

JToolBarHelper::preferences( 'com_COMPONENT_NAME' );
// e.g. for the core Content component, you would use JToolBarHelper::preferences( 'com_content' );

which is typically placed in the PHP file responsible for the Back-end output. (For example, using an MVC structure, you might place this code at the top of /PATH_TO_JOOMLA/administrator/components/com_COMPONENT_NAME/views/VIEW_NAME/tmpl/default.php.

This adds a Parameters button to the toolbar:

Toolbar newsfeed.png

Clicking on the toolbar button produces a pop-up window containing the form fields for each parameter defined in config.xml.

Note that there is no need to define default attributes for the <param /> elements in the config.xml file, since the default values will already have been saved in the installation of the Component.

2. Menu item specific parameters[edit]

A menu item is associated with a particular view from your Component's Front-end - following the menu link in the Front-end will display that view. Joomla! 1.5 allows you to define parameters for a particular view, so that a copy of those parameters can be associated with each menu item using the view. In addition, you can also choose to override the Component-wide default parameters defined as above, so that the override values will apply to the particular menu item.

The view parameters are defined in an XML file stored in the Front-end view output template (not to be confused with the site Template, which is different!) directory and with the same name as the template, i.e. /PATH_TO_JOOMLA/components/com_COMPONENT_NAME/views/VIEW_NAME/tmpl/TEMPLATE_NAME.xml. The structure of the file is:

<metadata>
  ...
  <state>
    ...
    <params>
      <param />
      ...
    </params>
    <advanced>
      <param />
      ...
    </advanced>
  </state>
</metadata>

See Standard parameter types for a full list of the core parameter types.

Displaying the forms for these parameters is handled automatically by the core com_menus component, which creates a number of slider panes on the right hand side (at least when viewed using the default Khepri backend site Template) of the menu item edit screen. Any parameters defined within the <params> tag will appear in the Parameters - Basic slider pane. Any parameters defined within the <advanced> tag will appear in the Parameters - Advanced slider pane.

The following screenshot shows the menu admin page for the Category 'List' layout. You can see that the Parameters - Basic slider pane is open, and contains form elements for five parameters. There are no 'Advanced' parameters for this view, and so the Parameters - Advanced slider pane is not shown:

Menu items edit.png

For the override of the Component-wide default parameters, com_menus uses the same config.xml file as above, so there is no need to define these parameters again. The override forms are automatically added to a slider pane named Parameters - Component. However, there are a number of changes from the forms used in the Preferences pop-up window (despite being based on the same config.xml file):

  • Any <param type="radio" /> parameter is shown not as a radio button form field, but by a drop-down list.
  • All drop-down lists (both those defined as such in config.xml, and those defined as radio buttons) are given an extra option. This extra option displays the text "Use Global" but has an associated value of an empty string. The "Use Global" option is set as the default option for the list. Thus, by default, these parameters will use the Component-wide default values, rather than overriding them. (However, note that any text box fields defined with a default value in config.xml retain that default value, and so will override the component-wide default value if that is different).

3. 'Article' specific parameters[edit]

These are defined in an XML file which can be stored anywhere you like, but is typically placed within the models folder of the Component Back-end (if you are using an MVC structure) and named according to the model to which they apply, i.e. PATH_TO_JOOMLA/administrator/components/com_COMPONENT_NAME/models/MODEL_NAME.xml. The XML file has the following structure:

<root>
  <params>
    <param />
    ...
  </params>
  <params group="GROUP_NAME">
    <param />
    ...
  </params>
  ...
</root>

As above, you can give the <root> element whatever name you wish. You can also have as many <params> groups as you like, though each group must have a group attribute with a different GROUP_NAME. If there are two or more <params> groups with the same GROUP_NAME, only the last one in the list will be considered.

To display the forms for these parameters in the Back-end of your Component, you will need to do a little work yourself. Firstly, you need to access the saved parameter data from the database. For this, you will need to identify both the location of the stored parameters data in the database, and the XML file that you are using to define the parameter form fields. Assuming that you have already created a $row variable to hold your component item (i.e. 'article') data, that the parameters data is stored in the params field of the $row, and that the XML file is located in the models folder as specified above, you could use the following code:

$paramsdata = $row->params;
$paramsdefs = JPATH_COMPONENT.DS.'models'.DS.'MODEL_NAME.xml';
$params = new JParameter( $paramsdata, $paramsdefs );

$this->assignRef('params', $params);

This code is typically placed in the View file (e.g. view.html.php) within the corresponding folder.

To display the parameters forms in slider panes (in the same way that they are displayed in the menu item Back-end), you should use the following code in the template file (e.g. PATH_TO_JOOMLA/administrator/com_COMPONENT_NAME/views/VIEW_NAME/tmpl/default.php):

$pane =& JPane::getInstance( 'sliders' );

echo $pane->startPane( 'content-pane' );

// First slider panel
// Create a slider panel with a title of SLIDER_PANEL_1_TITLE and a title id attribute of SLIDER_PANEL_1_NAME
echo $pane->startPanel( JText::_( 'SLIDER_PANEL_1_TITLE' ), 'SLIDER_PANEL_1_NAME' );
// Display the parameters defined in the <params> group with no 'group' attribute
echo $this->params->render( 'params' );
echo $pane->endPanel();

//Second slider panel
// Create a slider panel with a title of SLIDER_PANEL_2_TITLE and a title id attribute of SLIDER_PANEL_2_NAME
echo $pane->startPanel( JText::_( 'SLIDER_PANEL_2_TITLE' ), 'SLIDER_PANEL_2_NAME' );
// Display the parameters defined in the <params> group with the 'group' attribute of 'GROUP_NAME'
echo $this->params->render( 'params', 'GROUP_NAME' );
echo $pane->endPanel();

// Repeat for each additional slider panel required

echo $pane->endPane();

In order to save the parameters to the database you have to overload the bind() function which can be found in PATH_TO_JOOMLA/administrator/com_COMPONENT_NAME/tables/COMPONENT_NAME.php

function bind($array, $ignore = '')
{
	if (key_exists( 'params', $array ) && is_array( $array['params'] ))
	{
		$registry = new JRegistry();
		$registry->loadArray($array['params']);
		$array['params'] = $registry->toString();
	}
	return parent::bind($array, $ignore);
}

Accessing the parameters - frontend[edit]

The Front-end situation is a bit more complex than the Back-end. The 'standard' way to deal with parameters in the Front-end is to set up a cascade of overrides, as described above:

Item-specific overrides Menu-specific overrides Component-default

If you don't want to do this, then a little extra work is required

With overrides[edit]

The following code will access the Component-wide default parameters, already overridden with those for the menu item (if applicable):

<?php
  $params = &JComponentHelper::getParams( 'COMPONENT_NAME' );

  // e.g. for the com_weblinks component, you would use:
  // $params = &JComponentHelper::getParams( 'com_weblinks' )
?>

In an MVC structure, this code would be placed in the view.html.php file for the particular view required.

Assuming that the item parameters are stored in the params field, and that the particular item has been loaded into the $row object by the method, you would then add in the item parameters to the $params object using:

<?php
  $params->merge( new JParameter( &$row->params ) );
?>

Note that, in both cases (i.e. overrides by menu-specific parameters, and overrides by item-specific parameters), we aren't just doing overrides - we also add in any new parameters that weren't found in the defaults. In other words, the $params object ends up with all the parameters we need!

To access the value of a specific parameter, we would use:

<?php
  $params->get( 'PARAMETER_NAME' );

  // e.g. to obtain the value of 'parameter1', we use:
  // $params->get( 'parameter1' );
?>

It is important to realise that any merge carried out is persistent, so the following code (where for example you have an array containing the parameters sets for several items, and you want the parameters for each item to individually override the defaults) would not produce the result you might expect:

<?php
  foreach ($itemparamsgroup as $itemparams)
  {
    $params = &JComponentHelper::getParams( 'COMPONENT_NAME' );
    $params->merge( $itemparams );
    echo $params->get( 'PARAMETER_NAME' );
  }
?>

In such cases, you will need to use the non-override method, and then force the overrides manually, as described below.

Without overrides[edit]

There will be cases where you don't want to use the default override pattern. For example, you may want to ignore the menu-specific parameters, and have only the item-specific parameters overriding the defaults. This is a little more difficult to accomplish, although it can still be done.

You can access the Component-wide default parameter values, without the menu overrides, as follows:

<?php
  $component = JComponentHelper::getComponent( 'COMPONENT_NAME' );
  $params = new JParameter( $component->params );
?>

If you want to override these with the menu parameters, but without the 'persistence' effect described above, you can:

<?php
  $menuitemid = JRequest::getInt( 'Itemid' );
  if ($menuitemid)
  {
    $menu = JSite::getMenu();
    $menuparams = $menu->getParams( $menuitemid );
    $params->merge( $menuparams );
  }
?>

You can access the item parameters as before, and choose whether to merge them in using the code above, or simply store them in a separate object:

<?php
  $itemparams = new JParameter( $row->params );
?>

You can combine this code to achieve the effect that you want. For example, you could override the Component-wide defaults with the item-specific parameters, but ignore those for the menu. Or you could use the menu-specific parameters in some circumstances, and the item-specific ones in others. [Whenever you depart from the standard approach, though, you should be careful that you inform your users how your Component works. Users will expect your component to work the same way as those from the Joomla! core, so you should have a good reason for departing from this approach.]

Accessing the value of a particular parameter is done in the same way as described above.