Developers
Parameters
A parameter is a setting an administrator can change without editing code.
You declare them in XML; the CMS builds a form from the declaration, stores
what was entered as JSON in the extension's #__extensions row, and hands
them back to you as a Registry.
Declare one when a hub will reasonably want a different value from yours —
how many days ahead com_bookings lets people reserve an instrument, whether
a reservation needs approval. Do not declare one for every constant in the
extension. Each parameter is a screen an administrator has to understand and a
value your code has to keep working for; a setting nobody changes is a
liability with a form field attached.
This page is about declaring them. Config covers
reading them at runtime — Component::params(), $this->params, and the
Registry methods. Every parameter the shipped extensions declare is listed
in the configuration reference.
Where the declaration goes
| Kind | File | Root |
|---|---|---|
| Component | config/config.xml |
<config> |
| Module | its XML manifest | <config><fields name="params"> |
| Plugin | its XML manifest | <config><fields name="params"> |
| Template | templateDetails.xml |
<config><fields name="params"> |
The difference between the two shapes is a common half-hour: a component's
config.xml has <fieldset> children directly inside <config>, while
everything else wraps them in <fields name="params">. Put a component's
fieldsets inside a <fields> element and the Options screen comes up empty.
A component keeps its parameters in a separate file, and that file's root
element is <config> with <fieldset> children directly inside it:
<config>
<fieldset name="basic">
<field name="title" type="text" menu="hide" default="" label="COM_BLOG_CONFIG_TITLE_LABEL" description="COM_BLOG_CONFIG_TITLE_DESC" />
<field name="@spacer" type="spacer" default="" label="" description="" />
<field name="uploadpath" type="text" menu="hide" default="/site/blog" label="COM_BLOG_CONFIG_UPLOADS_LABEL" description="COM_BLOG_CONFIG_UPLOADS_DESC" />
</fieldset>
Everything else declares them inside its manifest, wrapped in a
<fields name="params">:
<config>
<fields name="params">
<fieldset name="basic">
<field name="filter_groups" type="usergroup"
description="PLG_DEBUG_FIELD_ALLOWED_GROUPS_DESC"
label="PLG_DEBUG_FIELD_ALLOWED_GROUPS_LABEL"
multiple="true"
size="10"
/>
Fieldsets
A <fieldset> becomes a tab or a titled group on the settings screen. The
names are conventional rather than enforced:
| Name | Where it appears |
|---|---|
basic |
The first tab. Most parameters belong here. |
advanced |
A second tab, for the layout and CSS class settings a module gets. |
| Anything else | Its own tab, labelled from the fieldset's label attribute or its name. |
com_blog uses basic, archive, entry and feeds; a component is free
to group its settings however reads best.
Fields
<field
name="introlength"
type="text"
default="300"
label="COM_BLOG_CONFIG_INTROLENGTH_LABEL"
description="COM_BLOG_CONFIG_INTROLENGTH_DESC"
/>
| Attribute | Meaning |
|---|---|
name |
The key. $params->get('introlength') reads it. Required. |
type |
Which field class renders it. Defaults to text. |
default |
The value used until an administrator saves something else. |
label |
A language key for the field's label. |
description |
A language key for its help text. |
required |
true to refuse an empty value. |
filter |
How the submitted value is cleaned — safehtml, integer, raw. |
class, size, cols, rows |
Passed to the rendered control. |
label and description are language keys, resolved from the extension's
own .ini file. Put them there rather than writing English into the
manifest. For a component that file is the administrator one, because the
Options screen runs in the administrator client; a label defined only in
site/language/ renders on the settings screen as its own key. See
Languages.
Fields that offer a fixed set of choices carry <option> children, whose
text is also a language key:
<field name="show_from" type="list" default="site"
label="COM_BLOG_CONFIG_DATA_SRC_LABEL"
description="COM_BLOG_CONFIG_DATA_SRC_DESC">
<option value="site">COM_BLOG_CONFIG_DATA_SRC_SITE</option>
<option value="member">COM_BLOG_CONFIG_DATA_SRC_MEMBER</option>
<option value="group">COM_BLOG_CONFIG_DATA_SRC_GROUP</option>
</field>
Field types
A type is resolved to a class in
Hubzero\Form\Fields by
Hubzero\Form\Helper::loadFieldType(): type="calendar" loads
Fields\Calendar. Two things are worth knowing about that lookup:
type="list"is special-cased toFields\Select, becauseListcannot be a PHP class name. Most of the tree writeslist.- An unrecognised type silently becomes a text box.
Form::loadField()callsloadFieldType('text')when the named class is not found. There is no error and no log line, so a typo intypecosts you the widget and nothing tells you — and an administrator then types free text where a drop-down should have constrained them. Check the name against the directory.
These are the types that exist:
| Type | Control |
|---|---|
text |
Single-line text box |
textarea |
Multi-line text box |
password |
Text box that obscures what is typed |
email, url, tel |
Text boxes with the matching HTML input type |
number, integer |
Numeric input; integer renders a range as a drop-down |
hidden |
Stored but not shown |
list |
Drop-down of the <option> children |
select |
The same class, under its own name |
groupedlist |
Drop-down with <group> headings |
combo |
Drop-down that also accepts a typed value |
radio |
Radio buttons |
checkbox, checkboxes |
One box, or a set of them |
spacer |
A visual separator; stores nothing |
calendar |
Text box with a date picker |
color |
Colour picker |
editor |
WYSIWYG editor |
media, file |
Media picker, file upload |
filelist, folderlist, imagelist |
Files, folders, or images from a named directory |
category |
Content categories |
tags |
Tag input |
user |
User picker |
usergroup |
User groups |
accesslevel |
Viewing access levels |
rules |
The permissions grid |
language, contentlanguage |
Installed languages, content languages |
country |
Country list |
timezone |
Time zones |
plugins |
Plugins in a given group |
templatestyle |
Installed template styles |
componentlayout, modulelayout |
Alternative layouts for a component or module |
menuitem |
Menu items |
sql |
Options from a query given in the field's query attribute |
cachehandler, sessionhandler, databaseconnection |
The configured handlers |
Permissions
Permissions are declared in a second file, config/access.xml, which names
the actions the component recognises, grouped into sections:
<access component="com_blog">
<section name="component">
<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
<action name="core.create" title="JACTION_CREATE" description="JACTION_CREATE_COMPONENT_DESC" />
<action name="core.delete" title="JACTION_DELETE" description="JACTION_DELETE_COMPONENT_DESC" />
<action name="core.edit" title="JACTION_EDIT" description="JACTION_EDIT_COMPONENT_DESC" />
<action name="core.edit.state" title="JACTION_EDITSTATE" description="JACTION_EDITSTATE_COMPONENT_DESC" />
<action name="core.edit.own" title="JACTION_EDITOWN" description="JACTION_EDITOWN_COMPONENT_DESC" />
</section>
The grid an administrator edits is a field in config.xml like any other,
of type="rules", pointing at a section of that file:
<field name="rules" type="rules" label="JCONFIG_PERMISSIONS_LABEL"
class="inputbox" validate="rules" filter="rules"
component="com_answers" section="component" />
See Users for how a controller then checks an action.
Where the values end up
Saved parameters are JSON in the params column of the extension's
#__extensions row. A module instance's parameters are in #__modules
instead, because the same module can be published several times with
different settings.
Nothing writes those columns at install time. Until an administrator saves
the settings screen the column is empty, and every $params->get() returns
its second argument — not the default in the manifest.
Always pass a default in code, and make it the same value as the one in the manifest:
$limit = (int) $params->get('introlength', 300);
A migration can seed the column instead, with the saveParams macro, if a
sensible value matters before anyone visits the screen. That is worth doing
when the parameter is not optional — when there is no sane fallback — and
unnecessary otherwise.
Rewritten and checked against 2.4-main @ 348f0057c2 on 2026-09-10.