https://docs.joomla.org/api.php?action=feedcontributions&user=Mvangeest&feedformat=atomJoomla! Documentation - User contributions [en]2016-12-09T15:21:23ZUser contributionsMediaWiki 1.23.14//docs.joomla.org/Manifest_filesManifest files2015-09-24T20:49:34Z<p>Mvangeest: Added information about the plugin attribute</p>
<hr />
<div>&lt;noinclude&gt;&lt;languages /&gt;&lt;/noinclude&gt;<br />
&lt;noinclude&gt;{{page|needs updating|}}&lt;/noinclude&gt;<br />
&lt;noinclude&gt;<br />
{{Joomla version|version=3.x}} {{Joomla version|version=2.5|status=eos}} <br />
&lt;/noinclude&gt;<br />
&lt;translate&gt;&lt;!--T:1--&gt;<br />
Within Joomla there are manifest files for all of the extensions. These files include the general installation information as well as parameters for the configuration of the [[S:MyLanguage/extension|extension]] itself. Since Joomla! 2.5, there are very few differences between the manifest file formats for the different [[S:MyLanguage/Extension types (technical definitions)|types of extensions]], allowing each type to access the full power of the Joomla! installer.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;==Naming conventions== &lt;!--T:2--&gt;<br />
The file must be named &lt;tt&gt;manifest.xml&lt;/tt&gt; or &lt;tt&gt;&lt;extension_name&gt;.xml&lt;/tt&gt; and located in the root directory of the installation package.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;==Syntax== &lt;!--T:3--&gt;&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== Root element === &lt;!--T:4--&gt;<br />
The primary tag of the installation file is:&lt;/translate&gt; <br />
&lt;source lang=xml&gt;&lt;extension&gt;&lt;/extension&gt;&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:5--&gt;<br />
This starting and closing tags are now valid for all extensions. The new tag &lt;code&gt;&lt;extension&gt;&lt;/code&gt; replaces the old &lt;code&gt;&lt;install&gt;&lt;/install&gt;&lt;/code&gt; from Joomla {{JVer|1.5}}. The following attributes are allowed within the tag:&lt;/translate&gt;<br />
<br />
{|class=&quot;wikitable&quot;<br />
|-<br />
! style=&quot;width: 150px&quot; | &lt;translate&gt;&lt;!--T:6--&gt;<br />
Attribute&lt;/translate&gt; || style=&quot;width: 150px&quot; | &lt;translate&gt;&lt;!--T:7--&gt;<br />
Values&lt;/translate&gt; || &lt;translate&gt;&lt;!--T:8--&gt;<br />
Applicable&amp;nbsp;to&lt;/translate&gt; || &lt;translate&gt;&lt;!--T:9--&gt;<br />
Description&lt;/translate&gt;<br />
|-<br />
| type || &lt;code&gt;component&lt;/code&gt;&lt;br /&gt;&lt;code&gt;file&lt;/code&gt;&lt;br /&gt;&lt;code&gt;language&lt;/code&gt;&lt;br /&gt;&lt;code&gt;library&lt;/code&gt;&lt;br /&gt;&lt;code&gt;module&lt;/code&gt;&lt;br /&gt;&lt;code&gt;package&lt;/code&gt;&lt;br /&gt;&lt;code&gt;plugin&lt;/code&gt;&lt;br /&gt;&lt;code&gt;template&lt;/code&gt; || &lt;translate&gt;&lt;!--T:10--&gt;<br />
All extensions&lt;/translate&gt;<br />
| &lt;translate&gt;&lt;!--T:11--&gt;<br />
This attribute describes the type of the extension for the installer. Based on this type further requirements to sub-tags apply.&lt;/translate&gt;<br />
|-<br />
| version<br />
| &lt;code&gt;2.5&lt;/code&gt;&lt;br /&gt;&lt;code&gt;3.0&lt;/code&gt; || &lt;translate&gt;&lt;!--T:12--&gt;<br />
All extensions&lt;/translate&gt;<br />
| &lt;translate&gt;&lt;!--T:13--&gt;<br />
String that identifies the version of Joomla for which this extension is developed.&lt;/translate&gt;<br />
|-<br />
| method<br />
| &lt;code&gt;install&lt;/code&gt;&lt;br /&gt;&lt;code&gt;upgrade&lt;/code&gt; || &lt;translate&gt;&lt;!--T:14--&gt;<br />
All extensions&lt;/translate&gt;<br />
| &lt;translate&gt;&lt;!--T:15--&gt;<br />
The default value &lt;code&gt;install&lt;/code&gt; will be also used if the method attribute is not used. The &lt;code&gt;install&lt;/code&gt; value means the installer will gracefully stop if it finds any existing file/folder of the new extension.&lt;/translate&gt;<br />
|-<br />
| client<br />
| &lt;code&gt;site&lt;/code&gt;&lt;br /&gt;&lt;code&gt;administrator&lt;/code&gt; || &lt;translate&gt;&lt;!--T:16--&gt;<br />
Modules&lt;/translate&gt;<br />
| &lt;translate&gt;&lt;!--T:17--&gt;<br />
The client attribute allows you to specify for which application client the new module is available.&lt;/translate&gt;<br />
|-<br />
| group<br />
| ''string'' || &lt;translate&gt;&lt;!--T:18--&gt;<br />
Plugins&lt;/translate&gt;<br />
| &lt;translate&gt;&lt;!--T:19--&gt;<br />
The group name specifies for which group of plugins the new plugin is available. The existing groups are the folder names within the directory &lt;tt&gt;/plugins&lt;/tt&gt;. The installer will create new folder names for group names that do not exist yet.&lt;/translate&gt;<br />
|}<br />
<br />
<br />
&lt;translate&gt;=== Metadata === &lt;!--T:20--&gt;&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:21--&gt;<br />
The following elements can be used to insert metadata. None of these elements are required; if they are present, they must be a child of the root element.&lt;/translate&gt;<br />
<br />
&lt;pre&gt;<br />
&lt;name&gt; &amp;ndash; raw component name (e.g. com_banners). <br />
&lt;author&gt; &amp;ndash; author's name (e.g. Joomla! Project)<br />
&lt;creationDate&gt; &amp;ndash; date of creation or release (e.g. April 2006)<br />
&lt;copyright&gt; &amp;ndash; a copyright statement (e.g. (C) 2005 - 2011 Open Source Matters. All rights reserved.)<br />
&lt;license&gt; &amp;ndash; a license statement (e.g. NU General Public License version 2 or later; see LICENSE.txt)<br />
&lt;authorEmail&gt; &amp;ndash; author's email address (e.g. admin@joomla.org)<br />
&lt;authorUrl&gt; &amp;ndash; URL to the author's website (e.g. www.joomla.org)<br />
&lt;version&gt; &amp;ndash; the version number of the extension (e.g. 1.6.0)<br />
&lt;description&gt; &amp;ndash; the description of the component. This is a translatable field. (e.g. COM_BANNERS_XML_DESCRIPTION)<br />
&lt;/pre&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:22--&gt;<br />
Note: The &lt;name&gt; and &lt;description&gt; tags are also translatable fields so that the name and description of the extension can be shown to the user in their native language.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== Front-end files === &lt;!--T:23--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files folder=&quot;from-folder&quot;&gt;<br />
&lt;filename&gt;example.php&lt;/filename&gt;<br />
&lt;folder&gt;examples&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:24--&gt;<br />
Files to copy to the front-end directory should be placed in the &lt;code&gt;&lt;files&gt;&lt;/code&gt; element. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from'''. Each file to copy must be represented by a &lt;code&gt;&lt;filename&gt;&lt;/code&gt; element. If you want to copy an entire folder at once, you can define it as a &lt;code&gt;&lt;folder&gt;&lt;/code&gt;.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;<br />
For '''plugins''', the raw name of the plugin should be placed in the &lt;code&gt;plugin&lt;/code&gt; attribute on the &lt;code&gt;&lt;filename&gt;&lt;/code&gt; element that points to the file containing the plugin's class. For example, in the case of a system plugin called &quot;example&quot; (full name &lt;code&gt;plg_system_example&lt;/code&gt;), use &lt;code&gt;&lt;filename plugin=&quot;example&quot;&gt;example.php&lt;/filename&gt;&lt;/code&gt;.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== Media files === &lt;!--T:25--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&gt;<br />
&lt;media folder=&quot;media&quot; destination=&quot;com_example&quot;&gt;<br />
&lt;filename&gt;com_example_logo.png&lt;/filename&gt;<br />
&lt;folder&gt;css&lt;/folder&gt;<br />
&lt;folder&gt;js&lt;/folder&gt;<br />
&lt;/media&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:26--&gt;<br />
This example will copy the file(s) (&lt;tt&gt;/media/com_example_logo.png&lt;/tt&gt;) and folders ( &lt;tt&gt;/media/css/&lt;/tt&gt; and &lt;tt&gt;/media/js/&lt;/tt&gt; ) listed to &lt;tt&gt;/media/com_example/&lt;/tt&gt;, creating the &lt;tt&gt;com_example&lt;/tt&gt; folder if required. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from''' (in this case, &lt;tt&gt;media&lt;/tt&gt;).&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:27--&gt;<br />
Extensions should be storing assets they need to be web accessible (JS, CSS, images etc) in &lt;code&gt;media&lt;/code&gt;. Amongst other things this feature was added as step in the progression to multi-site support and the eventual move of code files (PHP) out of the web accessible areas of the server.&lt;/translate&gt;<br />
<br />
Ref:<br />
* [https://groups.google.com/forum/#!msg/joomla-dev-cms/4CAASJqFY-k/PvPj14gP29EJ Google Groups - joomla-dev-cms thread]<br />
* [https://groups.google.com/forum/#!msg/joomla-dev-cms/uNmhX98sKbE/p8p68Jke680J Google Groups - joomla-dev-cms thread]<br />
<br />
&lt;translate&gt;=== Administration section === &lt;!--T:28--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;administration&gt;<br />
&lt;!-- various elements --&gt;<br />
&lt;/administration&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:29--&gt;<br />
The administration section is defined in the &lt;code&gt;&lt;administration&gt;&lt;/code&gt; element. Since only [[S:MyLanguage/Component|components]] apply to both the [[S:MyLanguage/Site (Application)|site]] and the [[S:MyLanguage/Administrator (Application)|administrator]], '''only component manifests can include this element'''.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;==== Back-end files ==== &lt;!--T:30--&gt;&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:31--&gt;<br />
Files to copy to the back-end directory should be placed in the &lt;code&gt;&lt;files&gt;&lt;/code&gt; element under the &lt;code&gt;&lt;administration&gt;&lt;/code&gt;. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from'''. See ''Front-end files'' for further rules.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;==== Menu links and submenus ==== &lt;!--T:32--&gt;&lt;/translate&gt;<br />
{{dablink|&lt;translate&gt;&lt;!--T:33--&gt;<br />
'''Version Note:''' Prior to Joomla 3.4, not having a &lt;code&gt;&lt;nowiki&gt;&lt;menu&gt;&lt;/nowiki&gt;&lt;/code&gt; tag in your manifest XML file still led to a menu item being created. This bug was fixed in Joomla 3.4, so if there is no &lt;code&gt;&lt;nowiki&gt;&lt;menu&gt;&lt;/nowiki&gt;&lt;/code&gt; tag in your manifest file, then no admin menu item is created for the component.&lt;/translate&gt;}}<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;menu&gt;COM_EXAMPLE&lt;/menu&gt;<br />
&lt;submenu&gt;<br />
&lt;!--<br />
Note that all &amp; must be escaped to &amp;amp; for the file to be valid<br />
XML and be parsed by the installer<br />
--&gt;<br />
&lt;menu link=&quot;anoption=avalue&amp;amp;anoption1=avalue1&quot;&gt;COM_EXAMPLE_SUBMENU_ANOPTION&lt;/menu&gt;<br />
&lt;menu view=&quot;viewname&quot;&gt;COM_EXAMPLE_SUBMENU_VIEWNAME&lt;/menu&gt;<br />
&lt;/submenu&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:34--&gt;<br />
The text for the main menu item for the component is defined in the &lt;code&gt;&lt;menu&gt;&lt;/code&gt; item, a child of &lt;code&gt;&lt;administration&gt;&lt;/code&gt;. A &lt;code&gt;&lt;submenu&gt;&lt;/code&gt; element may also be present (also a child of &lt;code&gt;&lt;administration&gt;&lt;/code&gt;), which may contain more menu items defined by &lt;code&gt;&lt;menu&gt;&lt;/code&gt;.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:35--&gt;<br />
Additionally, each &lt;code&gt;&lt;menu&gt;&lt;/code&gt; item can define the following attributes:&lt;/translate&gt;<br />
<br />
{| class=&quot;wikitable&quot;<br />
! style=&quot;width: 150px&quot; | &lt;translate&gt;&lt;!--T:36--&gt;<br />
Attribute&lt;/translate&gt; || &lt;translate&gt;&lt;!--T:37--&gt;<br />
Description&lt;/translate&gt;<br />
|-<br />
| link || &lt;translate&gt;&lt;!--T:38--&gt;<br />
A link to send the user to when the menu item is clicked&lt;/translate&gt;<br />
|-<br />
| img || &lt;translate&gt;&lt;!--T:39--&gt;<br />
The (relative) path to an image (16x16 pixels) to appear beside the menu item. <br />
&lt;u&gt;Must be an url compatible as a file too (e.g. no spaces) !&lt;/u&gt;&lt;/translate&gt;<br />
|-<br />
| alt ||<br />
|-<br />
| ''string'' || &lt;translate&gt;&lt;!--T:40--&gt;<br />
An URL parameter to add to the link. For example, &lt;code&gt;&lt;menu view=&quot;cpanel&quot;&gt;COM_EXAMPLE&lt;/menu&gt;&lt;/code&gt; in com_example's XML manifest would cause the URL of the menu item to be &lt;tt&gt;index.php?option=com_example&amp;view=cpanel&lt;/tt&gt;.&lt;/translate&gt;<br />
|-<br />
|}<br />
<br />
&lt;translate&gt;&lt;!--T:41--&gt;<br />
The value inside the tag is the menu's label. Unlike Joomla! 1.5, you can not use a natural language string. For example, if you would enter &quot;Example Component&quot; instead of COM_EXAMPLE, it would result in your component name appearing as example-component in the menu and you would be unable to provide a translation. In order to provide a translation you need to create a file named en-GB.com_example.sys.ini in administrator/languages/en-GB (you can use the manifest's &lt;code&gt;&amp;lt;languages&amp;gt;&lt;/code&gt; tag to copy it during installation) or in administrator/components/com_example/language/en-GB. In the latter case, you must not include the translation file in the &lt;code&gt;&amp;lt;languages&amp;gt;&lt;/code&gt; tag. As long as you have placed the language directory in your &lt;code&gt;&lt;files&gt;&lt;/code&gt; tag, it will be copied along when the component is being installed.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:42--&gt;<br />
The contents of that file should be:&lt;/translate&gt;<br />
<br />
&lt;source&gt;<br />
COM_EXAMPLE=&quot;Example Component&quot;<br />
COM_EXAMPLE_SUBMENU_ANOPTION=&quot;Another Option&quot;<br />
COM_EXAMPLE_SUBMENU_VIEWNAME=&quot;Another View&quot;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:43--&gt;<br />
Please note that the language string must be enclosed in double quotes, as per Joomla!'s translation standards. Important note: Joomla! 1.6 and later sorts the Component menu items based on the actual translation of the key you supply in your XML manifest. This means that the sorting order is correct no matter what you call your translation key and no matter which language the site is being displayed in. Essentially, Joomla! 1.6 fixed the wrong sorting of the Components menu experienced under Joomla! 1.5 for the majority (non-English speaking!) of Joomla! users.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== Configuration === &lt;!--T:44--&gt;&lt;/translate&gt;<br />
{{warning|&lt;translate&gt;&lt;!--T:45--&gt;<br />
Components '''do not support''' configuration definitions '''in the manifest'''. This is a way implemented in Joomla! 1.5. They can define configuration options for multiple levels using [[S:MyLanguage/Component configuration metadata|Component configuration metadata]].&lt;/translate&gt;}}<br />
&lt;translate&gt;&lt;!--T:46--&gt;<br />
The &lt;code&gt;&lt;config&gt;&lt;/code&gt; element, a child of the root, describes the configuration options for the extension. If applicable, the options will be shown by the appropriate Manager (Plugin Manager, Module Manager or Template Manager). '''Configuration options can also be defined in a separate file named &lt;code&gt;config.xml&lt;/code&gt;. Its root element should be &lt;code&gt;&lt;config&gt;&lt;/code&gt;.'''&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:47--&gt;<br />
Each fieldset must contain one or more &lt;code&gt;&lt;field&gt;&lt;/code&gt; elements, each representing a single [[S:MyLanguage/form field|form field]] with a label. See [[S:MyLanguage/Standard form field types|Standard form field types]] for a list of allowed form field types and example XML form field definitions.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== SQL === &lt;!--T:48--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;install&gt;<br />
&lt;sql&gt;<br />
&lt;file driver=&quot;mysql&quot; charset=&quot;utf8&quot;&gt;sql/example.install.sql&lt;/file&gt;<br />
&lt;/sql&gt;<br />
&lt;/install&gt;<br />
&lt;uninstall&gt;<br />
&lt;sql&gt;<br />
&lt;file driver=&quot;mysql&quot; charset=&quot;utf8&quot;&gt;sql/example.uninstall.sql&lt;/file&gt;<br />
&lt;/sql&gt;<br />
&lt;/uninstall&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:49--&gt;<br />
In the above example, we put the SQL files in the &lt;tt&gt;admin/sql&lt;/tt&gt; folder of the installation package. You have to include the &lt;tt&gt;sql&lt;/tt&gt; folder in the administration files (as described in ''Back-end files'').&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:50--&gt;<br />
You can execute SQL during the installation and/or uninstallation using the &lt;code&gt;&lt;install&gt;&lt;/code&gt; and &lt;code&gt;&lt;uninstall&gt;&lt;/code&gt; elements, respectively. A &lt;code&gt;&lt;sql&gt;&lt;/code&gt; element should appear as a child of these elements. &lt;code&gt;&lt;sql&gt;&lt;/code&gt; can contain any number of &lt;code&gt;&lt;file&gt;&lt;/code&gt; elements, each defining a single SQL file to execute. Their database driver types are described by the &lt;code&gt;driver&lt;/code&gt; attribute, their character sets by the &lt;code&gt;charset&lt;/code&gt; attribute.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;==== Update of the SQL schema ==== &lt;!--T:51--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;update&gt;<br />
&lt;schemas&gt;<br />
&lt;schemapath type=&quot;mysql&quot;&gt;sql/updates/mysql&lt;/schemapath&gt;<br />
&lt;schemapath type=&quot;sqlsrv&quot;&gt;sql/updates/sqlsrv&lt;/schemapath&gt;<br />
&lt;/schemas&gt;<br />
&lt;/update&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:52--&gt;<br />
Since 1.6, there is also an &lt;code&gt;&lt;update&gt;&lt;/code&gt; tag, which allows you to provide a series of SQL files to update the current schema.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== Language files === &lt;!--T:53--&gt;&lt;/translate&gt;<br />
&lt;translate&gt;&lt;!--T:54--&gt;<br />
In Joomla! 1.5, extension developers had to put extension language files in the Joomla! main language file, using the &amp;lt;languages&amp;gt;...&amp;lt;/languages&amp;gt; tag as shown below. '''This method can still be used in Joomla!''' {{JVer|3.x}}.&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;!-- Joomla! 1.5 language tag --&gt;<br />
&lt;languages folder=&quot;langfiles&quot;&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;en-GB.com_example.ini&lt;/language&gt;<br />
&lt;/languages&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:55--&gt;<br />
Since Joomla! 1.6 it has been encouraged placing your extension's language files in your extension folder. Joomla! will then automatically load your extension's language files.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:56--&gt;<br />
By storing extension language files in the extension folder, you gain the benefit of isolating and protecting your extension's language files. For example, an administrator removes a language from their Joomla! installation. Your extension's language files will not be removed. They will remain in place and will be available if the language is installed again.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:57--&gt;<br />
The structure of the language folder for frontend and backend is the same. You put them in the language tag (e.g. '''en-GB''' ) of each language in your language folder i.e. '''language/en-GB/'''. You have to specify those folders in the front-end and back-end files too.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:58--&gt;<br />
In your manifest you simply include the ''''language'''' folder in your files section, the sub-directories for each language automatically be copied. Inside the &lt;files&gt; group you simply add a &lt;folder&gt; element alongside the items in the '''&lt;files&gt;''' group as shown in this example:&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files&gt;<br />
&lt;filename plugin=&quot;alpha&quot;&gt;alpha.php&lt;/filename&gt;<br />
&lt;folder&gt;sql&lt;/folder&gt;<br />
&lt;folder&gt;language&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:59--&gt;<br />
It is also notable that both ways can work together. Here is an example from core:&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files&gt;<br />
&lt;filename plugin=&quot;languagecode&quot;&gt;languagecode.php&lt;/filename&gt;<br />
&lt;filename&gt;index.html&lt;/filename&gt;<br />
&lt;folder&gt;language&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;languages&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;language/en-GB/en-GB.plg_system_languagecode.ini&lt;/language&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;language/en-GB/en-GB.plg_system_languagecode.sys.ini&lt;/language&gt;<br />
&lt;/languages&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:60--&gt;<br />
The advantages of this solution are the following:&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:61--&gt;<br />
All ini files present in the core folder have precedence over the files in the extension language/ folder.<br />
For example a sys.ini file will always be loaded from core folders in back-end if it exists, except when installing an extension which contains a sys.ini file in a language folder. In that case and only that case, the sys.ini file in the extension folder will display its translated content at install time. This is very handy as a developer can have 2 sys.ini files with different contents. A description of the successful install as well as a tutorial in back-end for example.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:62--&gt;<br />
Also, it is much easier for a user needing an ini file for an extension that does not provide it in the language desired, to add it in the main folders. No risk for it to be deleted in case of uninstalling the extension by mistake or any other reason.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:63--&gt;<br />
See also:<br />
*[[S:MyLanguage/J2.5:Making non-core language packs|Making non-core language packs]]<br />
*[[S:MyLanguage/Creating language packs for extensions in Joomla 2.5|Creating language packs for extensions in Joomla 2.5]]&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:64--&gt;<br />
During development you can turn on language debugging in the Joomla! global configuration. So you can investigate if a problems arises. As of 3.2, this is necessary to help debug as en-GB is '''always''' loaded first when not in debug mode to prevent displaying Constants.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== Script file === &lt;!--T:65--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;scriptfile&gt;example.script.php&lt;/scriptfile&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:66--&gt;<br />
An optional '''script file''' (PHP code that is run before, during and/or after installation, uninstallation and upgrading) can be defined using a &lt;code&gt;&lt;scriptfile&gt;&lt;/code&gt; element. This file should contain a class named &quot;&lt;element_name&gt;InstallerScript&quot; where &lt;element_name&gt; is the name of your extension (e.g. com_componentname, mod_modulename, etc.). Plugins requires to state the group (e.g. plgsystempluginname). Library packages do not support scriptfiles. The structure of the class is as follows:&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
class com_componentnameInstallerScript<br />
{<br />
/**<br />
* Constructor<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*/<br />
public function __construct(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called before any type of action<br />
*<br />
* @param string $route Which action is happening (install|uninstall|discover_install|update)<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function preflight($route, JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called after any type of action<br />
*<br />
* @param string $route Which action is happening (install|uninstall|discover_install|update)<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function postflight($route, JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on installation<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function install(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on update<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function update(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on uninstallation<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*/<br />
public function uninstall(JAdapterInstance $adapter);<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;=== Update servers === &lt;!--T:67--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;updateservers&gt;<br />
&lt;server type=&quot;extension&quot; priority=&quot;1&quot; name=&quot;Extension Update Site&quot;&gt;http://example.com/extension.xml&lt;/server&gt;<br />
&lt;server type=&quot;collection&quot; priority=&quot;2&quot; name=&quot;Collection Update Site&quot;&gt;http://example.com/collection.xml&lt;/server&gt;<br />
&lt;/updateservers&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:68--&gt;<br />
Update servers can be defined in the &lt;code&gt;&lt;updateservers&gt;&lt;/code&gt; element, a child of the root. This element may contain one or more &lt;code&gt;&lt;server&gt;&lt;/code&gt; element, each describing a location to fetch updates from. Each &lt;code&gt;&lt;server&gt;&lt;/code&gt; item can define the following attributes:&lt;/translate&gt;<br />
<br />
{| class=&quot;wikitable&quot;<br />
! style=&quot;width: 150px&quot; | &lt;translate&gt;&lt;!--T:69--&gt;<br />
Attribute&lt;/translate&gt; || style=&quot;width: 150px&quot; | &lt;translate&gt;&lt;!--T:70--&gt;<br />
Values&lt;/translate&gt; || &lt;translate&gt;&lt;!--T:71--&gt;<br />
Description&lt;/translate&gt;<br />
|-<br />
| type || &lt;code&gt;extension&lt;/code&gt;&lt;br /&gt;&lt;code&gt;collection&lt;/code&gt; || &lt;translate&gt;&lt;!--T:72--&gt;<br />
The update server type&lt;/translate&gt;<br />
|-<br />
| priority || ''integer'' || &lt;translate&gt;&lt;!--T:73--&gt;<br />
The priority of the update server&lt;/translate&gt;<br />
|-<br />
| name || ''string'' || &lt;translate&gt;&lt;!--T:74--&gt;<br />
The name of the update server&lt;/translate&gt;<br />
|}<br />
<br />
&lt;translate&gt;&lt;!--T:75--&gt;<br />
More info:<br />
* [[S:MyLanguage/J2.5:Developing a MVC Component/Adding an update server|Building a Joomla! Extension - Adding an update server]]<br />
* [[S:MyLanguage/J2.5:Managing Component Updates|Managing Component Updates in Joomla 2.5]]&lt;/translate&gt;<br />
<br />
&lt;translate&gt;== Examples == &lt;!--T:76--&gt;<br />
For a real-life example, see [https://github.com/joomla/joomla-cms/blob/2.5.x/administrator/components/com_banners/banners.xml the manifest of the Banner component in the latest version of Joomla! 2.5].&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:77--&gt;<br />
The Joomla testing process uses several extensions to test whether the installer works correctly. The latest versions of the manifests of these extensions are:&lt;/translate&gt;<br />
<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/com_alpha/alpha.xml com_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/mod_alpha/mod_alpha.xml mod_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/plg_system_alpha/alpha.xml plg_system_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/tpl_simple/templateDetails.xml tpl_simple manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/lng_xx-XX/xx-XX.xml lng_xx-XX manifest]<br />
<br />
&lt;translate&gt;== Contributors == &lt;!--T:78--&gt;&lt;/translate&gt;<br />
*[[User:akede|Alex Kempkens]]<br />
*[[User:dperaza|Daniel Peraza]]<br />
*[[User:nikosdion|Nicholas K. Dionysopoulos]]<br />
*[[User:mrs.siam|Prasit Gebsaap]]<br />
*[[User:cppl|Craig Phillips]]<br />
<br />
&lt;noinclude&gt;<br />
&lt;translate&gt;<br />
&lt;!--T:79--&gt;<br />
[[Category:Development]]<br />
[[Category:Extension development]]<br />
[[Category:Specifications]]<br />
&lt;/translate&gt;<br />
&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Manifest_filesManifest files2015-09-19T14:05:19Z<p>Mvangeest: Adjusted wording</p>
<hr />
<div>&lt;noinclude&gt;&lt;languages /&gt;&lt;/noinclude&gt;<br />
&lt;noinclude&gt;{{page|needs updating|}}&lt;/noinclude&gt;<br />
&lt;noinclude&gt;<br />
{{Joomla version|version=3.x}} {{Joomla version|version=2.5|time=and after|status=eos}} <br />
&lt;/noinclude&gt;<br />
&lt;translate&gt;&lt;!--T:1--&gt;<br />
Within Joomla there are manifest files for all of the extensions. These files include the general installation information as well as parameters for the configuration of the [[S:MyLanguage/extension|extension]] itself. Since Joomla! 2.5, there are very few differences between the manifest file formats for the different [[S:MyLanguage/Extension types (technical definitions)|types of extensions]], allowing each type to access the full power of the Joomla! installer.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;==Naming conventions== &lt;!--T:2--&gt;<br />
The file must be named &lt;tt&gt;manifest.xml&lt;/tt&gt; or &lt;tt&gt;&lt;extension_name&gt;.xml&lt;/tt&gt; and located in the root directory of the installation package.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;==Syntax== &lt;!--T:3--&gt;&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== Root element === &lt;!--T:4--&gt;<br />
The primary tag of the installation file is:&lt;/translate&gt; <br />
&lt;source lang=xml&gt;&lt;extension&gt;&lt;/extension&gt;&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:5--&gt;<br />
This starting and closing tags are now valid for all extensions. The new tag &lt;code&gt;&lt;extension&gt;&lt;/code&gt; replaces the old &lt;code&gt;&lt;install&gt;&lt;/install&gt;&lt;/code&gt; from Joomla {{JVer|1.5}}. The following attributes are allowed within the tag:&lt;/translate&gt;<br />
<br />
{|class=&quot;wikitable&quot;<br />
|-<br />
! style=&quot;width: 150px&quot; | &lt;translate&gt;&lt;!--T:6--&gt;<br />
Attribute&lt;/translate&gt; || style=&quot;width: 150px&quot; | &lt;translate&gt;&lt;!--T:7--&gt;<br />
Values&lt;/translate&gt; || &lt;translate&gt;&lt;!--T:8--&gt;<br />
Applicable&amp;nbsp;to&lt;/translate&gt; || &lt;translate&gt;&lt;!--T:9--&gt;<br />
Description&lt;/translate&gt;<br />
|-<br />
| type || &lt;code&gt;component&lt;/code&gt;&lt;br /&gt;&lt;code&gt;file&lt;/code&gt;&lt;br /&gt;&lt;code&gt;language&lt;/code&gt;&lt;br /&gt;&lt;code&gt;library&lt;/code&gt;&lt;br /&gt;&lt;code&gt;module&lt;/code&gt;&lt;br /&gt;&lt;code&gt;package&lt;/code&gt;&lt;br /&gt;&lt;code&gt;plugin&lt;/code&gt;&lt;br /&gt;&lt;code&gt;template&lt;/code&gt; || &lt;translate&gt;&lt;!--T:10--&gt;<br />
All extensions&lt;/translate&gt;<br />
| &lt;translate&gt;&lt;!--T:11--&gt;<br />
This attribute describes the type of the extension for the installer. Based on this type further requirements to sub-tags apply.&lt;/translate&gt;<br />
|-<br />
| version<br />
| &lt;code&gt;2.5&lt;/code&gt;&lt;br /&gt;&lt;code&gt;3.0&lt;/code&gt; || &lt;translate&gt;&lt;!--T:12--&gt;<br />
All extensions&lt;/translate&gt;<br />
| &lt;translate&gt;&lt;!--T:13--&gt;<br />
String that identifies the version of Joomla for which this extension is developed.&lt;/translate&gt;<br />
|-<br />
| method<br />
| &lt;code&gt;install&lt;/code&gt;&lt;br /&gt;&lt;code&gt;upgrade&lt;/code&gt; || &lt;translate&gt;&lt;!--T:14--&gt;<br />
All extensions&lt;/translate&gt;<br />
| &lt;translate&gt;&lt;!--T:15--&gt;<br />
The default value &lt;code&gt;install&lt;/code&gt; will be also used if the method attribute is not used. The &lt;code&gt;install&lt;/code&gt; value means the installer will gracefully stop if it finds any existing file/folder of the new extension.&lt;/translate&gt;<br />
|-<br />
| client<br />
| &lt;code&gt;site&lt;/code&gt;&lt;br /&gt;&lt;code&gt;administrator&lt;/code&gt; || &lt;translate&gt;&lt;!--T:16--&gt;<br />
Modules&lt;/translate&gt;<br />
| &lt;translate&gt;&lt;!--T:17--&gt;<br />
The client attribute allows you to specify for which application client the new module is available.&lt;/translate&gt;<br />
|-<br />
| group<br />
| ''string'' || &lt;translate&gt;&lt;!--T:18--&gt;<br />
Plugins&lt;/translate&gt;<br />
| &lt;translate&gt;&lt;!--T:19--&gt;<br />
The group name specifies for which group of plugins the new plugin is available. The existing groups are the folder names within the directory &lt;tt&gt;/plugins&lt;/tt&gt;. The installer will create new folder names for group names that do not exist yet.&lt;/translate&gt;<br />
|}<br />
<br />
<br />
&lt;translate&gt;=== Metadata === &lt;!--T:20--&gt;&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:21--&gt;<br />
The following elements can be used to insert metadata. None of these elements are required; if they are present, they must be a child of the root element.&lt;/translate&gt;<br />
<br />
&lt;pre&gt;<br />
&lt;name&gt; &amp;ndash; raw component name (e.g. com_banners). <br />
&lt;author&gt; &amp;ndash; author's name (e.g. Joomla! Project)<br />
&lt;creationDate&gt; &amp;ndash; date of creation or release (e.g. April 2006)<br />
&lt;copyright&gt; &amp;ndash; a copyright statement (e.g. (C) 2005 - 2011 Open Source Matters. All rights reserved.)<br />
&lt;license&gt; &amp;ndash; a license statement (e.g. NU General Public License version 2 or later; see LICENSE.txt)<br />
&lt;authorEmail&gt; &amp;ndash; author's email address (e.g. admin@joomla.org)<br />
&lt;authorUrl&gt; &amp;ndash; URL to the author's website (e.g. www.joomla.org)<br />
&lt;version&gt; &amp;ndash; the version number of the extension (e.g. 1.6.0)<br />
&lt;description&gt; &amp;ndash; the description of the component. This is a translatable field. (e.g. COM_BANNERS_XML_DESCRIPTION)<br />
&lt;/pre&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:22--&gt;<br />
Note: The &lt;name&gt; and &lt;description&gt; tags are also translatable fields so that the name and description of the extension can be shown to the user in their native language.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== Front-end files === &lt;!--T:23--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files folder=&quot;from-folder&quot;&gt;<br />
&lt;filename&gt;example.php&lt;/filename&gt;<br />
&lt;folder&gt;examples&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:24--&gt;<br />
Files to copy to the front-end directory should be placed in the &lt;code&gt;&lt;files&gt;&lt;/code&gt; element. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from'''. Each file to copy must be represented by a &lt;code&gt;&lt;filename&gt;&lt;/code&gt; element. If you want to copy an entire folder at once, you can define it as a &lt;code&gt;&lt;folder&gt;&lt;/code&gt;.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== Media files === &lt;!--T:25--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&gt;<br />
&lt;media folder=&quot;media&quot; destination=&quot;com_example&quot;&gt;<br />
&lt;filename&gt;com_example_logo.png&lt;/filename&gt;<br />
&lt;folder&gt;css&lt;/folder&gt;<br />
&lt;folder&gt;js&lt;/folder&gt;<br />
&lt;/media&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:26--&gt;<br />
This example will copy the file(s) (&lt;tt&gt;/media/com_example_logo.png&lt;/tt&gt;) and folders ( &lt;tt&gt;/media/css/&lt;/tt&gt; and &lt;tt&gt;/media/js/&lt;/tt&gt; ) listed to &lt;tt&gt;/media/com_example/&lt;/tt&gt;, creating the &lt;tt&gt;com_example&lt;/tt&gt; folder if required. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from''' (in this case, &lt;tt&gt;media&lt;/tt&gt;).&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:27--&gt;<br />
Extensions should be storing assets they need to be web accessible (JS, CSS, images etc) in &lt;code&gt;media&lt;/code&gt;. Amongst other things this feature was added as step in the progression to multi-site support and the eventual move of code files (PHP) out of the web accessible areas of the server.&lt;/translate&gt;<br />
<br />
Ref:<br />
* [https://groups.google.com/forum/#!msg/joomla-dev-cms/4CAASJqFY-k/PvPj14gP29EJ Google Groups - joomla-dev-cms thread]<br />
* [https://groups.google.com/forum/#!msg/joomla-dev-cms/uNmhX98sKbE/p8p68Jke680J Google Groups - joomla-dev-cms thread]<br />
<br />
&lt;translate&gt;=== Administration section === &lt;!--T:28--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;administration&gt;<br />
&lt;!-- various elements --&gt;<br />
&lt;/administration&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:29--&gt;<br />
The administration section is defined in the &lt;code&gt;&lt;administration&gt;&lt;/code&gt; element. Since only [[S:MyLanguage/Component|components]] apply to both the [[S:MyLanguage/Site (Application)|site]] and the [[S:MyLanguage/Administrator (Application)|administrator]], '''only component manifests can include this element'''.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;==== Back-end files ==== &lt;!--T:30--&gt;&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:31--&gt;<br />
Files to copy to the back-end directory should be placed in the &lt;code&gt;&lt;files&gt;&lt;/code&gt; element under the &lt;code&gt;&lt;administration&gt;&lt;/code&gt;. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from'''. See ''Front-end files'' for further rules.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;==== Menu links and submenus ==== &lt;!--T:32--&gt;&lt;/translate&gt;<br />
{{dablink|&lt;translate&gt;&lt;!--T:33--&gt;<br />
'''Version Note:''' Prior to Joomla 3.4, not having a &lt;code&gt;&lt;nowiki&gt;&lt;menu&gt;&lt;/nowiki&gt;&lt;/code&gt; tag in your manifest XML file still led to a menu item being created. This bug was fixed in Joomla 3.4, so if there is no &lt;code&gt;&lt;nowiki&gt;&lt;menu&gt;&lt;/nowiki&gt;&lt;/code&gt; tag in your manifest file, then no admin menu item is created for the component.&lt;/translate&gt;}}<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;menu&gt;COM_EXAMPLE&lt;/menu&gt;<br />
&lt;submenu&gt;<br />
&lt;!--<br />
Note that all &amp; must be escaped to &amp;amp; for the file to be valid<br />
XML and be parsed by the installer<br />
--&gt;<br />
&lt;menu link=&quot;anoption=avalue&amp;amp;anoption1=avalue1&quot;&gt;COM_EXAMPLE_SUBMENU_ANOPTION&lt;/menu&gt;<br />
&lt;menu view=&quot;viewname&quot;&gt;COM_EXAMPLE_SUBMENU_VIEWNAME&lt;/menu&gt;<br />
&lt;/submenu&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:34--&gt;<br />
The text for the main menu item for the component is defined in the &lt;code&gt;&lt;menu&gt;&lt;/code&gt; item, a child of &lt;code&gt;&lt;administration&gt;&lt;/code&gt;. A &lt;code&gt;&lt;submenu&gt;&lt;/code&gt; element may also be present (also a child of &lt;code&gt;&lt;administration&gt;&lt;/code&gt;), which may contain more menu items defined by &lt;code&gt;&lt;menu&gt;&lt;/code&gt;.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:35--&gt;<br />
Additionally, each &lt;code&gt;&lt;menu&gt;&lt;/code&gt; item can define the following attributes:&lt;/translate&gt;<br />
<br />
{| class=&quot;wikitable&quot;<br />
! style=&quot;width: 150px&quot; | &lt;translate&gt;&lt;!--T:36--&gt;<br />
Attribute&lt;/translate&gt; || &lt;translate&gt;&lt;!--T:37--&gt;<br />
Description&lt;/translate&gt;<br />
|-<br />
| link || &lt;translate&gt;&lt;!--T:38--&gt;<br />
A link to send the user to when the menu item is clicked&lt;/translate&gt;<br />
|-<br />
| img || &lt;translate&gt;&lt;!--T:39--&gt;<br />
The (relative) path to an image (16x16 pixels) to appear beside the menu item. <br />
&lt;u&gt;Must be an url compatible as a file too (e.g. no spaces) !&lt;/u&gt;&lt;/translate&gt;<br />
|-<br />
| alt ||<br />
|-<br />
| ''string'' || &lt;translate&gt;&lt;!--T:40--&gt;<br />
An URL parameter to add to the link. For example, &lt;code&gt;&lt;menu view=&quot;cpanel&quot;&gt;COM_EXAMPLE&lt;/menu&gt;&lt;/code&gt; in com_example's XML manifest would cause the URL of the menu item to be &lt;tt&gt;index.php?option=com_example&amp;view=cpanel&lt;/tt&gt;.&lt;/translate&gt;<br />
|-<br />
|}<br />
<br />
&lt;translate&gt;&lt;!--T:41--&gt;<br />
The value inside the tag is the menu's label. Unlike Joomla! 1.5, you can not use a natural language string. For example, if you would enter &quot;Example Component&quot; instead of COM_EXAMPLE, it would result in your component name appearing as example-component in the menu and you would be unable to provide a translation. In order to provide a translation you need to create a file named en-GB.com_example.sys.ini in administrator/languages/en-GB (you can use the manifest's &lt;code&gt;&amp;lt;languages&amp;gt;&lt;/code&gt; tag to copy it during installation) or in administrator/components/com_example/language/en-GB. In the latter case, you must not include the translation file in the &lt;code&gt;&amp;lt;languages&amp;gt;&lt;/code&gt; tag. As long as you have placed the language directory in your &lt;code&gt;&lt;files&gt;&lt;/code&gt; tag, it will be copied along when the component is being installed.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:42--&gt;<br />
The contents of that file should be:&lt;/translate&gt;<br />
<br />
&lt;source&gt;<br />
COM_EXAMPLE=&quot;Example Component&quot;<br />
COM_EXAMPLE_SUBMENU_ANOPTION=&quot;Another Option&quot;<br />
COM_EXAMPLE_SUBMENU_VIEWNAME=&quot;Another View&quot;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:43--&gt;<br />
Please note that the language string must be enclosed in double quotes, as per Joomla!'s translation standards. Important note: Joomla! 1.6 and later sorts the Component menu items based on the actual translation of the key you supply in your XML manifest. This means that the sorting order is correct no matter what you call your translation key and no matter which language the site is being displayed in. Essentially, Joomla! 1.6 fixed the wrong sorting of the Components menu experienced under Joomla! 1.5 for the majority (non-English speaking!) of Joomla! users.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== Configuration === &lt;!--T:44--&gt;&lt;/translate&gt;<br />
{{warning|&lt;translate&gt;&lt;!--T:45--&gt;<br />
Components '''do not support''' configuration definitions '''in the manifest'''. This is a way implemented in Joomla! 1.5. They can define configuration options for multiple levels using [[S:MyLanguage/Component configuration metadata|Component configuration metadata]].&lt;/translate&gt;}}<br />
&lt;translate&gt;&lt;!--T:46--&gt;<br />
The &lt;code&gt;&lt;config&gt;&lt;/code&gt; element, a child of the root, describes the configuration options for the extension. If applicable, the options will be shown by the appropriate Manager (Plugin Manager, Module Manager or Template Manager). '''Configuration options can also be defined in a separate file named &lt;code&gt;config.xml&lt;/code&gt;. Its root element should be &lt;code&gt;&lt;config&gt;&lt;/code&gt;.'''&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:47--&gt;<br />
Each fieldset must contain one or more &lt;code&gt;&lt;field&gt;&lt;/code&gt; elements, each representing a single [[S:MyLanguage/form field|form field]] with a label. See [[S:MyLanguage/Standard form field types|Standard form field types]] for a list of allowed form field types and example XML form field definitions.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== SQL === &lt;!--T:48--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;install&gt;<br />
&lt;sql&gt;<br />
&lt;file driver=&quot;mysql&quot; charset=&quot;utf8&quot;&gt;sql/example.install.sql&lt;/file&gt;<br />
&lt;/sql&gt;<br />
&lt;/install&gt;<br />
&lt;uninstall&gt;<br />
&lt;sql&gt;<br />
&lt;file driver=&quot;mysql&quot; charset=&quot;utf8&quot;&gt;sql/example.uninstall.sql&lt;/file&gt;<br />
&lt;/sql&gt;<br />
&lt;/uninstall&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:49--&gt;<br />
In the above example, we put the SQL files in the &lt;tt&gt;admin/sql&lt;/tt&gt; folder of the installation package. You have to include the &lt;tt&gt;sql&lt;/tt&gt; folder in the administration files (as described in ''Back-end files'').&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:50--&gt;<br />
You can execute SQL during the installation and/or uninstallation using the &lt;code&gt;&lt;install&gt;&lt;/code&gt; and &lt;code&gt;&lt;uninstall&gt;&lt;/code&gt; elements, respectively. A &lt;code&gt;&lt;sql&gt;&lt;/code&gt; element should appear as a child of these elements. &lt;code&gt;&lt;sql&gt;&lt;/code&gt; can contain any number of &lt;code&gt;&lt;file&gt;&lt;/code&gt; elements, each defining a single SQL file to execute. Their database driver types are described by the &lt;code&gt;driver&lt;/code&gt; attribute, their character sets by the &lt;code&gt;charset&lt;/code&gt; attribute.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;==== Update of the SQL schema ==== &lt;!--T:51--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;update&gt;<br />
&lt;schemas&gt;<br />
&lt;schemapath type=&quot;mysql&quot;&gt;sql/updates/mysql&lt;/schemapath&gt;<br />
&lt;schemapath type=&quot;sqlsrv&quot;&gt;sql/updates/sqlsrv&lt;/schemapath&gt;<br />
&lt;/schemas&gt;<br />
&lt;/update&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:52--&gt;<br />
Since 1.6, there is also an &lt;code&gt;&lt;update&gt;&lt;/code&gt; tag, which allows you to provide a series of SQL files to update the current schema.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== Language files === &lt;!--T:53--&gt;&lt;/translate&gt;<br />
&lt;translate&gt;&lt;!--T:54--&gt;<br />
In Joomla! 1.5, extension developers had to put extension language files in the Joomla! main language file, using the &amp;lt;languages&amp;gt;...&amp;lt;/languages&amp;gt; tag as shown below. '''This method can still be used in Joomla!''' {{JVer|3.x}}.&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;!-- Joomla! 1.5 language tag --&gt;<br />
&lt;languages folder=&quot;langfiles&quot;&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;en-GB.com_example.ini&lt;/language&gt;<br />
&lt;/languages&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:55--&gt;<br />
Since Joomla! 1.6 it has been encouraged placing your extension's language files in your extension folder. Joomla! will then automatically load your extension's language files.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:56--&gt;<br />
By storing extension language files in the extension folder, you gain the benefit of isolating and protecting your extension's language files. For example, an administrator removes a language from their Joomla! installation. Your extension's language files will not be removed. They will remain in place and will be available if the language is installed again.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:57--&gt;<br />
The structure of the language folder for frontend and backend is the same. You put them in the language tag (e.g. '''en-GB''' ) of each language in your language folder i.e. '''language/en-GB/'''. You have to specify those folders in the front-end and back-end files too.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:58--&gt;<br />
In your manifest you simply include the ''''language'''' folder in your files section, the sub-directories for each language automatically be copied. Inside the &lt;files&gt; group you simply add a &lt;folder&gt; element alongside the items in the '''&lt;files&gt;''' group as shown in this example:&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files&gt;<br />
&lt;filename plugin=&quot;alpha&quot;&gt;alpha.php&lt;/filename&gt;<br />
&lt;folder&gt;sql&lt;/folder&gt;<br />
&lt;folder&gt;language&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:59--&gt;<br />
It is also notable that both ways can work together. Here is an example from core:&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files&gt;<br />
&lt;filename plugin=&quot;languagecode&quot;&gt;languagecode.php&lt;/filename&gt;<br />
&lt;filename&gt;index.html&lt;/filename&gt;<br />
&lt;folder&gt;language&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;languages&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;language/en-GB/en-GB.plg_system_languagecode.ini&lt;/language&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;language/en-GB/en-GB.plg_system_languagecode.sys.ini&lt;/language&gt;<br />
&lt;/languages&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:60--&gt;<br />
The advantages of this solution are the following:&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:61--&gt;<br />
All ini files present in the core folder have precedence over the files in the extension language/ folder.<br />
For example a sys.ini file will always be loaded from core folders in back-end if it exists, except when installing an extension which contains a sys.ini file in a language folder. In that case and only that case, the sys.ini file in the extension folder will display its translated content at install time. This is very handy as a developer can have 2 sys.ini files with different contents. A description of the successful install as well as a tutorial in back-end for example.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:62--&gt;<br />
Also, it is much easier for a user needing an ini file for an extension that does not provide it in the language desired, to add it in the main folders. No risk for it to be deleted in case of uninstalling the extension by mistake or any other reason.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:63--&gt;<br />
See also:<br />
*[[S:MyLanguage/J2.5:Making non-core language packs|Making non-core language packs]]<br />
*[[S:MyLanguage/Creating language packs for extensions in Joomla 2.5|Creating language packs for extensions in Joomla 2.5]]&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:64--&gt;<br />
During development you can turn on language debugging in the Joomla! global configuration. So you can investigate if a problems arises. As of 3.2, this is necessary to help debug as en-GB is '''always''' loaded first when not in debug mode to prevent displaying Constants.&lt;/translate&gt;<br />
<br />
&lt;translate&gt;=== Script file === &lt;!--T:65--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;scriptfile&gt;example.script.php&lt;/scriptfile&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:66--&gt;<br />
An optional '''script file''' (PHP code that is run before, during and/or after installation, uninstallation and upgrading) can be defined using a &lt;code&gt;&lt;scriptfile&gt;&lt;/code&gt; element. This file should contain a class named &quot;&lt;element_name&gt;InstallerScript&quot; where &lt;element_name&gt; is the name of your extension (e.g. com_componentname, mod_modulename, etc.). Plugins requires to state the group (e.g. plgsystempluginname). Library packages do not support scriptfiles. The structure of the class is as follows:&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
class com_componentnameInstallerScript<br />
{<br />
/**<br />
* Constructor<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*/<br />
public function __construct(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called before any type of action<br />
*<br />
* @param string $route Which action is happening (install|uninstall|discover_install|update)<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function preflight($route, JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called after any type of action<br />
*<br />
* @param string $route Which action is happening (install|uninstall|discover_install|update)<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function postflight($route, JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on installation<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function install(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on update<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function update(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on uninstallation<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*/<br />
public function uninstall(JAdapterInstance $adapter);<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;=== Update servers === &lt;!--T:67--&gt;&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;updateservers&gt;<br />
&lt;server type=&quot;extension&quot; priority=&quot;1&quot; name=&quot;Extension Update Site&quot;&gt;http://example.com/extension.xml&lt;/server&gt;<br />
&lt;server type=&quot;collection&quot; priority=&quot;2&quot; name=&quot;Collection Update Site&quot;&gt;http://example.com/collection.xml&lt;/server&gt;<br />
&lt;/updateservers&gt;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:68--&gt;<br />
Update servers can be defined in the &lt;code&gt;&lt;updateservers&gt;&lt;/code&gt; element, a child of the root. This element may contain one or more &lt;code&gt;&lt;server&gt;&lt;/code&gt; element, each describing a location to fetch updates from. Each &lt;code&gt;&lt;server&gt;&lt;/code&gt; item can define the following attributes:&lt;/translate&gt;<br />
<br />
{| class=&quot;wikitable&quot;<br />
! style=&quot;width: 150px&quot; | &lt;translate&gt;&lt;!--T:69--&gt;<br />
Attribute&lt;/translate&gt; || style=&quot;width: 150px&quot; | &lt;translate&gt;&lt;!--T:70--&gt;<br />
Values&lt;/translate&gt; || &lt;translate&gt;&lt;!--T:71--&gt;<br />
Description&lt;/translate&gt;<br />
|-<br />
| type || &lt;code&gt;extension&lt;/code&gt;&lt;br /&gt;&lt;code&gt;collection&lt;/code&gt; || &lt;translate&gt;&lt;!--T:72--&gt;<br />
The update server type&lt;/translate&gt;<br />
|-<br />
| priority || ''integer'' || &lt;translate&gt;&lt;!--T:73--&gt;<br />
The priority of the update server&lt;/translate&gt;<br />
|-<br />
| name || ''string'' || &lt;translate&gt;&lt;!--T:74--&gt;<br />
The name of the update server&lt;/translate&gt;<br />
|}<br />
<br />
&lt;translate&gt;&lt;!--T:75--&gt;<br />
More info:<br />
* [[S:MyLanguage/J2.5:Developing a MVC Component/Adding an update server|Building a Joomla! Extension - Adding an update server]]<br />
* [[S:MyLanguage/J2.5:Managing Component Updates|Managing Component Updates in Joomla 2.5]]&lt;/translate&gt;<br />
<br />
&lt;translate&gt;== Examples == &lt;!--T:76--&gt;<br />
For a real-life example, see [https://github.com/joomla/joomla-cms/blob/2.5.x/administrator/components/com_banners/banners.xml the manifest of the Banner component in the latest version of Joomla! 2.5].&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:77--&gt;<br />
The Joomla testing process uses several extensions to test whether the installer works correctly. The latest versions of the manifests of these extensions are:&lt;/translate&gt;<br />
<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/com_alpha/alpha.xml com_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/mod_alpha/mod_alpha.xml mod_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/plg_system_alpha/alpha.xml plg_system_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/tpl_simple/templateDetails.xml tpl_simple manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/lng_xx-XX/xx-XX.xml lng_xx-XX manifest]<br />
<br />
&lt;translate&gt;== Contributors == &lt;!--T:78--&gt;&lt;/translate&gt;<br />
*[[User:akede|Alex Kempkens]]<br />
*[[User:dperaza|Daniel Peraza]]<br />
*[[User:nikosdion|Nicholas K. Dionysopoulos]]<br />
*[[User:mrs.siam|Prasit Gebsaap]]<br />
*[[User:cppl|Craig Phillips]]<br />
<br />
&lt;noinclude&gt;<br />
&lt;translate&gt;<br />
&lt;!--T:79--&gt;<br />
[[Category:Development]]<br />
[[Category:Extension development]]<br />
[[Category:Specifications]]<br />
&lt;/translate&gt;<br />
&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Creating_a_language_definition_fileCreating a language definition file2015-09-17T21:03:41Z<p>Mvangeest: Rewrote article for Joomla 3 based on the Specification page, the PHP docs, the JLanguage source code, core language files and user comments. The warning is no longer necessary.</p>
<hr />
<div>&lt;noinclude&gt;&lt;languages /&gt;&lt;/noinclude&gt;<br />
{{Joomla version|version=3.x|comment=&lt;translate&gt;&lt;!--T:9--&gt;<br />
series&lt;/translate&gt;}}<br />
{{-}}<br />
{{notice|&lt;translate&gt;&lt;!--T:11--&gt;<br />
The page [[S:MyLanguage/Specification of language files|Specification of language files]] contains some more details that should be '''verified''' - as it is no longer completely up-to-date - and then merged into this page.&lt;/translate&gt;}}<br />
<br />
&lt;translate&gt;<br />
&lt;!--T:2--&gt;<br />
Joomla! language definition files are written in the very basic ''[[wikipedia:INI file|INI file format]]''. They must be saved ''using the UTF-8 encoding''. Blank lines and lines beginning with &lt;code&gt;;&lt;/code&gt; are ignored and the latter may be used to add comments to the file. Each line consists of a key-value pair separated by an equals sign like this:<br />
&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:10--&gt;<br />
&lt;source lang=&quot;ini&quot;&gt;<br />
KEY=&quot;value&quot;<br />
&lt;/source&gt;&lt;/translate&gt;<br />
<br />
&lt;translate&gt;<br />
&lt;!--T:3--&gt;<br />
where &lt;code&gt;KEY&lt;/code&gt; is a string to be translated and &lt;code&gt;value&lt;/code&gt; is the translated string. For example:<br />
&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;ini&quot;&gt;<br />
ADDITIONAL_INFORMATION=&quot;Additional Information&quot;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;<br />
Different versions of Joomla have used slightly different ways to read language files (namely a custom parser and the native PHP INI parser, the latter of which was buggy in PHP 5.2 and older), leading to different rules for what exactly is allowed in keys and values. Language files that abide by the following rules should work under many versions of Joomla, but at least under Joomla {{jver|3.x}} and newer.<br />
&lt;/translate&gt;<br />
<br />
&lt;translate&gt;<br />
&lt;!--T:5--&gt;<br />
The &lt;code&gt;KEY&lt;/code&gt; should only use ASCII characters. It should only contain capital letters, digits, underscores and hyphens, and it should start with a capital letter. (Dots (&lt;code&gt;.&lt;/code&gt;) are formally allowed, but do not appear to be completely supported.) It is a convention to replace any whitespace in the string to be translated with underscores. If more than one entry has the same key, the last one to be encountered is the one that will be used. When you use the key in a &lt;code&gt;JText::_&lt;/code&gt; call, the case does not matter as strings are folded to upper case before searching takes place. So &lt;code&gt;additional_information&lt;/code&gt;, &lt;code&gt;Additional_Information&lt;/code&gt; or even &lt;code&gt;AdDiTiOnAl_InFoRmAtIoN&lt;/code&gt; will be matched.<br />
&lt;/translate&gt;<br />
<br />
&lt;translate&gt;<br />
&lt;!--T:6--&gt;<br />
The &lt;code&gt;value&lt;/code&gt; should always be surrounded by double-quote characters (&lt;code&gt;&quot;&lt;/code&gt;), as in the example. The value itself cannot include double-quote characters (&lt;code&gt;&quot;&lt;/code&gt;), although single-quote characters (&lt;code&gt;'&lt;/code&gt;) are valid. Use &lt;code&gt;&quot;_QQ_&quot;&lt;/code&gt;, ''including the double quotes'', to place a double-quote character in your value. For example, to attach the value &lt;code&gt;&lt;nowiki&gt;&lt;span class=&quot;red&quot;&gt;Warning!&lt;/span&gt;&lt;/nowiki&gt;&lt;/code&gt; to the key &lt;code&gt;WARNING_TEXT&lt;/code&gt;, use following line:<br />
&lt;/translate&gt;<br />
<br />
&lt;source lang=&quot;ini&quot;&gt;<br />
WARNING_TEXT=&quot;&lt;span class=&quot;_QQ_&quot;red&quot;_QQ_&quot;&gt;Warning!&lt;/span&gt;&quot;<br />
&lt;/source&gt;<br />
<br />
&lt;translate&gt;<br />
Note that these rules are stricter than required by [http://php.net/manual/en/function.parse-ini-file.php the PHP INI parser]. For example, the PHP INI parser allows you to omit the double quotes around the value as long as it does not contain certain characters. Using the rules above should make it much easier to avoid mistakes like forgetting double quotes when they ''are'' required.<br />
&lt;/translate&gt;<br />
<br />
&lt;translate&gt;<br />
&lt;!--T:7--&gt;<br />
Information about the changes in the language file format between the Joomla 1.5, 2.5 and 3.x series can be found on the page [[S:MyLanguage/Specification of language files|Specification of language files]].<br />
&lt;/translate&gt;<br />
<br />
&lt;noinclude&gt;<br />
----<br />
&lt;references/&gt;<br />
&lt;translate&gt;<br />
&lt;!--T:8--&gt;<br />
[[Category:Tutorials]]<br />
[[Category:Language Development]]<br />
&lt;/translate&gt;<br />
&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Specification_of_language_filesSpecification of language files2015-09-17T19:52:03Z<p>Mvangeest: This page says it is &quot;not merged back&quot; because it is &quot;currently under development&quot;. Things have stabilised by now and the main page should be updated. Some things mentioned here are no longer true.</p>
<hr />
<div>{{version|2.5,3.1}}<br />
{{JSplit}}<br />
{{incomplete}}<br />
{{merge|Creating a language definition file}}<br />
This page explains the changes of the language file specification from version 1.5 to 2.5. As this is currently under development it is not merged back to the central specification page. <br />
<br />
The 1.5 specification is described in [[Creating a language definition file]].<br />
<br />
== Overview of changes in Joomla 3.2 {{JVer|3.2}} ==<br />
<br />
Starting with Joomla! 3.2, en-GB is automatically load first, then the xx-XX language strings. This is to ensure there is always a fallback to a string value. What this does is prevent the display of a 'constant' if the xx-XX language ini file is broken or a translation string is missing. <br />
<br />
== Overview of changes in Joomla 2.5 {{JVer|2.5}} == <br />
# The KEY is now defined to be<br />
## without any whitespace. All whitespace shall be converted into a underscore '_'<br />
## All KEY's in the frontend shall include a prefix of the extension<br />
<br />
Additional information from a new [http://groups.google.com/group/joomla-dev-framework/browse_thread/thread/4cfac49cddb8c54a?hl=en-GB thread]<br />
<br />
So, the implications on ini file format:<br />
# As previously mentioned, our keys will have to change. Spaces are not allowed. The general practice will be to use underscores for spacing. Also, the plan is to name space strings, so that you would end up with something like COM_EXAMPLE_MYKEY for your key. According to the php manual, The characters {}|&amp;~![()^&quot; cannot be used in keys. There are also reserved words for keys: null, yes, no, true, false, on, off, none. Note: the COM_EXAMPLE_ prefix is not mandatory as of Joomla! 1.6/1.7, but it is advisable to follow this convention to avoid naming collisions with other extensions.<br />
# The syntax for the value has also changed. According to the PHP manual, if a value in the ini file contains any non-alphanumeric characters it needs to be enclosed in double-quotes (&quot;). That will basically mean all of our values will have to be enclosed in quotes, as a space is non alpha numeric. If you want to include a double-quote in your string, you can use an html entity like &amp; quot; or the default &quot;_QQ_&quot;. Finally, according to the PHP manual, the {}|&amp;~![()^&quot; characters have a special meaning in the value. Unfortunately, they don't really unpack what that special meaning is - anybody have experience in this area? Reply from infograf768: My guess is that they can't be used if not enclosed in double quotes. Note from nikosdion: I concur with infograf768's comment. Also, all translation strings should be in double quotation marks.<br />
# Comment syntax has changed, as we are typically using pound signs (#) and the standard parser requires semi colons (;). Note from nikosdion: you MUST use semicolons, otherwise your language files will not load<br />
<br />
Typical comment and string:<br />
&lt;source lang=&quot;xml&quot;&gt;; A comment<br />
COM_KEY_CONSTANT=&quot;My value is &quot;_QQ_&quot;great!&quot;_QQ_&quot;. I like it&quot;&lt;/source&gt;<br />
<br />
Note: If your INI format is invalid, the results are not well defined. Most versions of PHP will load your language file up to the point where an error occurs, but throw no error message whatsoever.<br />
<br />
Note: Only ASCII characters are supported in language keys<br />
<br />
&lt;noinclude&gt;[[Category:Language Management]]&lt;/noinclude&gt;<br />
<br />
== Updating your Joomla 1.5 language files to work on Joomla 2.5 == <br />
Using the native php ini parser for language files has many benefits including much faster performance.<br />
<br />
Basically, you have two options:<br />
<br />
# The Eclipse solution (or any other Coding Platform), extremely easy as well:<br />
##Search your file for *.ini in your project of choice. Then use the following search/replace values to automatically, replace exisiting quotes, add quotes to string values and update your comments<br />
##Double quotes are now not allowed and this can be easily bypassed by searching &quot; and replace with '<br />
##Put a closing double quote at end of line if not empty or a comment. Find ^((?!#).+)\R replace with $1&quot;\R<br />
##Put an opening quote at start of translated string if not empty or comment. Find ^((?!#).+?\=)(.+)\R replace with $1&quot;$2\R<br />
##Now replace the hash comments with the new semi colon. Find ^# and replace with ;<br />
##Remove any illegal strings that can prevent files loading. Find ^(null|yes|no|true|false|on|off|none)=(.+)\R and replace with nothing.<br />
<br />
Note from nikosdion: I have written a reliable Joomla! 1.5 to Joomla! 1.6 language converter which abides to these conventions. You can find it at [http://snipt.net/nikosdion/langconvert/ my Snipt page]<br />
<br />
==Language file naming conventions and precedence==<br />
All language files follow the naming convention language.extension.ini. For example, the Great British English translation file of com_foobar is named en-GB.com_foobar.ini.<br />
<br />
Translation files are stored inside the respective system-wide language directory. For example, front-end language files for GB English are stored inside language/en-GB. So, the front-end GB English translation file of com_foobar has a full path of language/en-GB/en-GB.com_foobar.ini. Likewise, its back-end translation has a full path of administrator/language/en-GB/en-GB.com_foobar.ini. You must specify system-wide translation files in your extension's XML manifest file, otherwise they will not be installed. These system-wide language files are loaded first by Joomla!. In order to place your language files in your XML manifest file, you can use the same syntax as with Joomla! 1.5, i.e.:<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;languages folder=&quot;path/to/language&quot;&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;en-GB/en-GB.com_foobar.ini&lt;/language&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;en-GB/en-GB.com_foobar.sys.ini&lt;/language&gt;<br />
&lt;/languages&gt;<br />
&lt;/source&gt;<br />
<br />
Each extension can also have &quot;local&quot; translation files, inside its own front- or back-end directory. For example, you can have a language ini for GB English in administrator/components/com_foobar/language/en-GB/en-GB.com_foobar.ini. These &quot;local&quot; files do not need to be mentioned in your extension's XML manifest file. In fact, a user can always create a language directory inside your extension's directory, create a sub-directory named after his language and inside it create a language INI file with his desired language overrides.<br />
<br />
Joomla! extension's must also specify a sys.ini file which is used <br />
* a. during the extension's installation, to allow localising the post-installation messages, <br />
* b. to build the administrator Components menu, <br />
* c. to localise component parameters and menu parameters <br />
* d. and in the Extension Manager-&gt;Manage. <br />
These follow a similar naming convention with the main language files and can be stored in the site's back-end. If they are only stored there, their strings will not be used when installing. For example, com_foobar's GB English sys.ini file is stored in administrator/language/en-GB/en-GB.com_foobar.sys.ini and its variant in administrator/components/com_foobar/language/en-GB/en-GB.com_foobar.sys.ini.<br />
<br />
'''''IMPORTANT!''''' For the sys.ini to load automatically upon installation it MUST be stored inside the extension's directory. In other words, a system-wide sys.ini file WILL NOT be loaded upon installation. If there is only ONE sys.ini file present in the extension language directory, that one will be loaded for back-end normal usage. <br />
<br />
'''''IMPORTANT!''''' the ini files stored system wide ALWAYS override the ones stored in the extension language folder, except for the sys.ini at installation time. One can therefore have 2 sys.ini files. Also using different values for the manifest key &lt;description&gt;COM_FOOBAR_XML_DESCRIPTION&lt;/description&gt; in the sys.ini file from the extension language folder used at installation and the ini file will provide a different display when editing the extension.<br />
<br />
The menu item shown in the Components menu always comes from the translation key COM_FOOBAR for a component named com_foobar (that is, your component's installation directory uppercased). This is substantially different than the way Joomla! 1.5 menu.ini files used to work!<br />
<br />
The best way to wrap your head around these conventions is to download a popular Joomla! 1.6 compatible extension from the JED and analyse its contents, in the true Free and Open Source Software spirit.<br />
<br />
==Loading any language file, anywhere==<br />
Joomla! automatically loads the translation files when you are accessing a component. In order to load arbitrary language files in your extensions, you can use the following code:<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$language = JFactory::getLanguage();<br />
$language-&gt;load('com_yourcomponentname');<br />
&lt;/source&gt;<br />
<br />
Note from elkuku: Or shorter using PHP 5's chaining:<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JFactory::getLanguage()-&gt;load('com_yourcomponentname');<br />
&lt;/source&gt;<br />
<br />
Another cool trick you can do is to load arbitrary front-end and back-end language files of any component and language. For example, you may want to load the English language file and mix it with the user's current language. This means that untranslated strings will appear in English and not as untranslated keys. You can use something like this for the back-end language files:<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$language = JFactory::getLanguage();<br />
$language-&gt;load('com_yourcomponentname', JPATH_ADMINISTRATOR, 'en-GB', true);<br />
$language-&gt;load('com_yourcomponentname', JPATH_ADMINISTRATOR, null, true);<br />
&lt;/source&gt;<br />
<br />
And to load the front-end language files, using the same trick:<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$language = JFactory::getLanguage();<br />
$language-&gt;load('com_yourcomponentname', JPATH_SITE, 'en-GB', true);<br />
$language-&gt;load('com_yourcomponentname', JPATH_SITE, null, true);<br />
&lt;/source&gt;<br />
<br />
==Related discussion threads in the development mailing list==<br />
* [http://groups.google.com/group/joomla-dev-cms/browse_thread/thread/af76ac17eecbfe2d/fbfbbd15c5c60d71?lnk=gst&amp;q=language#fbfbbd15c5c60d71 Another language question concerning 1.6 Optionen]<br />
* [http://groups.google.com/group/joomla-dev-cms/browse_thread/thread/213f8e6a885e42fe/310bb187a26d5965?lnk=gst&amp;q=language#310bb187a26d5965 Here is a proposal from the com_localise team - Comments?]<br />
* [http://groups.google.com/group/joomla-dev-cms/browse_thread/thread/8ef8d089546b7734/ffea9ba8a60a5927?lnk=gst&amp;q=language#ffea9ba8a60a5927 Hardcoded punctuation creates issues in language files Optionen]<br />
* [http://groups.google.com/group/joomla-dev-cms/browse_thread/thread/446ccaa42baafc66/af422d0b2de81c2f?lnk=gst&amp;q=language#af422d0b2de81c2f Language String Namespaces]<br />
<br />
&lt;noinclude&gt;<br />
[[Category: Languages]]<br />
[[Category:Specifications]]<br />
[[Category:References]]<br />
[[Category:Language Development]]<br />
[[Category:Specifications Version 2.5]]<br />
&lt;/noinclude&gt;<br />
[[Category:Needs to be marked for translation]]</div>Mvangeest//docs.joomla.org/Creating_a_language_definition_fileCreating a language definition file2015-09-17T18:19:08Z<p>Mvangeest: Added warning: this page's contents are *not* - at least not entirely - valid for the 3 series. The Specification page should be merged into this one.</p>
<hr />
<div>&lt;noinclude&gt;&lt;languages /&gt;&lt;/noinclude&gt;<br />
<br />
{{Joomla version|version=3.x|comment=&lt;translate&gt;&lt;!--T:9--&gt;<br />
series&lt;/translate&gt;}}<br />
{{warning|This page was written for Joomla {{jver|1.5}}. Joomla {{jver|3.x}} has slightly different requirements, as explained in [[Specification of language files]]. See [http://php.net/manual/en/function.parse-ini-string.php the PHP documentation] for more details.}}<br />
<br />
&lt;translate&gt;<br />
&lt;!--T:1--&gt;<br />
Important note: Joomla language &lt;code&gt;.ini&lt;/code&gt; files must be saved as UTF-8<br />
&lt;/translate&gt;<br />
<br />
&lt;translate&gt;<br />
&lt;!--T:2--&gt;<br />
The format of language definition files is very basic. Blanks lines and lines beginning with “#” are ignored and the latter may be used to add comments to the file. Each line consists of a pair of strings separated by an equals sign like this :<br />
&lt;/translate&gt;<br />
<br />
&lt;translate&gt;&lt;!--T:10--&gt;<br />
KEY=Value&lt;/translate&gt;<br />
<br />
&lt;translate&gt;<br />
&lt;!--T:3--&gt;<br />
where “''KEY''” is a string to be translated and “''Value''” is the translated string. For example :<br />
&lt;/translate&gt;<br />
<br />
ADDITIONAL_INFORMATION=&quot;Additional Information&quot;<br />
<br />
&lt;translate&gt;<br />
&lt;!--T:4--&gt;<br />
The “''KEY''” must be in all capitals or the string will not be found. The case of the source string does not matter as strings are folded to upper case before searching takes place. So “additional information”, “Additional Information” or even “AdDiTiOnAl InFoRmAtIoN” will be matched.<br />
&lt;/translate&gt;<br />
<br />
&lt;translate&gt;<br />
&lt;!--T:5--&gt;<br />
The “''KEY''” can include spaces and other punctuation characters but there should not be any spaces either side of the equals sign as spaces are significant. If more than one entry has the same left-hand side, the last one to be encountered is the one that will be used.<br />
&lt;/translate&gt;<br />
<br />
&lt;translate&gt;<br />
&lt;!--T:6--&gt;<br />
The &quot;''VALUE''&quot; cannot include double-quote characters (&quot;). To get a double-quote character you must use the HTML special character sequence &quot;&amp;amp;quot;&quot; instead. Single-quote characters (') are valid.<br />
&lt;/translate&gt;<br />
<br />
&lt;translate&gt;<br />
&lt;!--T:7--&gt;<br />
More information about the discussed changes for the Joomla 2.5 and 3.x series can be found on the page [[S:MyLanguage/Specification of language files|Specification of language files]]<br />
&lt;/translate&gt; <br />
<br />
&lt;noinclude&gt;<br />
----<br />
&lt;references/&gt;<br />
&lt;translate&gt;<br />
&lt;!--T:8--&gt;<br />
[[Category:Tutorials]]<br />
[[Category:Language Development]]<br />
&lt;/translate&gt;<br />
&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Retrieving_request_data_using_JInputRetrieving request data using JInput2015-09-06T00:16:43Z<p>Mvangeest: Fixed own incorrect edit (revision 68329): a single PHP object was meant (see revision 68300)</p>
<hr />
<div>{{version|2.5,3.x|platform=11.1,12.1}}<br />
==Requirements==<br />
To be able to use JInput as described here, you must be using Joomla 2.5.0 or above.<br />
<br />
Please note there are known issues with JInput and Magic Quotes (Deprecated in PHP 5.3.0 and removed in PHP 5.4.0). Most servers have these turned off - however it is important to bear this in mind whilst developing a component. For this reason all core components in Joomla 2.5.x still use JRequest. As of Joomla 3.0+ magic quotes is required to be disabled and thus this is no longer an issue.<br />
<br />
==Using JInput==<br />
To use JInput you must first create the object by using this code:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$jinput = JFactory::getApplication()-&gt;input;&lt;/source&gt;<br />
<br />
===Getting Values===<br />
To get a value from JInput, you can use:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;get('varname', 'default_value', 'filter');&lt;/source&gt;<br />
<br />
The filter defaults to &lt;code&gt;cmd&lt;/code&gt;.<br />
<br />
{{notice|The code fragments in the following list show the ''implementation'' of the filters (assuming the value you want to retrieve is stored in &lt;code&gt;$source&lt;/code&gt;). You do not need them to ''use'' JInput; all you need for using JInput is the code shown above.}}<br />
<br />
Available filters are:<br />
<br />
*INT<br />
*INTEGER<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Only use the first integer value<br />
preg_match('/-?[0-9]+/', (string) $source, $matches);<br />
$result = @ (int) $matches[0];<br />
&lt;/source&gt;<br />
*UINT<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Only use the first integer value<br />
preg_match('/-?[0-9]+/', (string) $source, $matches);<br />
$result = @ abs((int) $matches[0]);<br />
&lt;/source&gt;<br />
*FLOAT<br />
*DOUBLE<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Only use the first floating point value<br />
preg_match('/-?[0-9]+(\.[0-9]+)?/', (string) $source, $matches);<br />
$result = @ (float) $matches[0];<br />
&lt;/source&gt;<br />
*BOOL<br />
*BOOLEAN<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$result = (bool) $source;<br />
&lt;/source&gt;<br />
*WORD<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Only allow characters a-z, and underscores<br />
$result = (string) preg_replace('/[^A-Z_]/i', '', $source);<br />
&lt;/source&gt;<br />
*ALNUM<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Allow a-z and 0-9 only<br />
$result = (string) preg_replace('/[^A-Z0-9]/i', '', $source);<br />
&lt;/source&gt;<br />
*CMD<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Allow a-z, 0-9, underscore, dot, dash. Also remove leading dots from result. <br />
$result = (string) preg_replace('/[^A-Z0-9_\.-]/i', '', $source);<br />
$result = ltrim($result, '.');<br />
&lt;/source&gt;<br />
*BASE64<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Allow a-z, 0-9, slash, plus, equals.<br />
$result = (string) preg_replace('/[^A-Z0-9\/+=]/i', '', $source);<br />
&lt;/source&gt;<br />
*STRING<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Converts the input to a plain text string; strips all tags / attributes.<br />
$result = (string) $this-&gt;_remove($this-&gt;_decode((string) $source));<br />
&lt;/source&gt;<br />
*HTML<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Converts the input to a string; strips all HTML tags / attributes.<br />
$result = (string) $this-&gt;_remove($this-&gt;_decode((string) $source));<br />
&lt;/source&gt;<br />
*ARRAY<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Attempts to convert the input to an array.<br />
$result = (array) $source;<br />
&lt;/source&gt;<br />
*PATH<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Converts the input into a string and validates it as a path. (e.g. path/to/file.png or path/to/dir)<br />
// Note: Does NOT accept absolute paths, or paths ending in a trailing slash.<br />
// For a visual representation of the pattern matching used, see http://www.regexper.com/#^[A-Za-z0-9_-]%2B[A-Za-z0-9_\.-]*%28[\\\\\%2F][A-Za-z0-9_-]%2B[A-Za-z0-9_\.-]*%29*%24<br />
// Will return null if the input was invalid.<br />
$pattern = '/^[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*([\\\\\/][A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$/';<br />
preg_match($pattern, (string) $source, $matches);<br />
$result = @ (string) $matches[0];<br />
&lt;/source&gt;<br />
*RAW<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// The raw input. No sanitation provided.<br />
$result = $source;<br />
&lt;/source&gt;<br />
*USERNAME<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Strips all invalid username characters.<br />
$result = (string) preg_replace('/[\x00-\x1F\x7F&lt;&gt;&quot;\'%&amp;]/', '', $source)<br />
&lt;/source&gt;<br />
<br />
Alternatively instead of adding the filter you can use the JInput type specific methods:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Instead of:<br />
$input-&gt;get('name', '', 'STR');<br />
// you can use:<br />
$input-&gt;getString('name', '');<br />
<br />
// Instead of:<br />
$input-&gt;get('memberId', 0, 'INT');<br />
// you can use:<br />
$input-&gt;getInt('memberId', 0);<br />
&lt;/source&gt;<br />
<br />
To retrieve an object, you can use:<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;get('varname', null, null);&lt;/source&gt;<br />
<br />
===Getting Multiple Values===<br />
<br />
To retrieve a number of values you can use the &lt;code&gt;getArray()&lt;/code&gt; method:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$fooValues = $jinput-&gt;getArray(array('var1' =&gt; '', 'var2' =&gt; '', 'var3' =&gt; ''));<br />
&lt;/source&gt;<br />
<br />
or, if you want to determine the data to get step by step:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$fooArray = array();<br />
$fooArray['var1'] = '';<br />
$fooArray['var2'] = '';<br />
$fooArray['var3'] = '';<br />
$fooValues = $jinput-&gt;getArray($fooArray);<br />
&lt;/source&gt;<br />
<br />
The &lt;code&gt;$fooValues&lt;/code&gt; will be an array that consists of the same keys as used in &lt;code&gt;$fooArray&lt;/code&gt;, but with values attached.<br />
<br />
You can also specify different filters for each of the inputs:<br />
<br />
&lt;source lang=&quot;php&gt;<br />
$fooValues = $jinput-&gt;getArray(array(<br />
'var1' =&gt; 'int',<br />
'var2' =&gt; 'float',<br />
'var3' =&gt; 'word'<br />
));<br />
&lt;/source&gt;<br />
<br />
You can also nest arrays to get more complicated hierarchies of values:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$fooValues = $jinput-&gt;getArray(array(<br />
'jform' =&gt; array(<br />
'title' =&gt; 'string',<br />
'quantity' =&gt; 'int',<br />
'state' =&gt; 'int'<br />
)<br />
));<br />
&lt;/source&gt;<br />
<br />
===Getting Values from a Specific Super Global===<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;get-&gt;get('varname', 'default_value', 'filter');&lt;/source&gt;<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;post-&gt;get('varname', 'default_value', 'filter');&lt;/source&gt;<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;server-&gt;get('varname', 'default_value', 'filter');&lt;/source&gt;<br />
<br />
===Setting Values===<br />
<br />
To set a value via JInput, you can use:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$jinput-&gt;set('varname', $foo);&lt;/source&gt;<br />
<br />
===Retrieving File Data===<br />
<br />
The format that PHP returns file data in for arrays can at times be awkward, especially when dealing with arrays of files. JInputFiles provides a convenient interface for making life a little easier, grouping the data by file.<br />
<br />
Suppose you have a form like:<br />
&lt;source lang=&quot;html4strict&quot;&gt;<br />
&lt;form action=&quot;&lt;?php echo JRoute::_('index.php?option=com_example&amp;task=file.submit'); ?&gt;&quot; enctype=&quot;multipart/form-data&quot; method=&quot;post&quot;&gt;<br />
&lt;input type=&quot;file&quot; name=&quot;jform1[test][]&quot; /&gt;<br />
&lt;input type=&quot;file&quot; name=&quot;jform1[test][]&quot; /&gt;<br />
&lt;input type=&quot;submit&quot; value=&quot;submit&quot; /&gt;<br />
&lt;/form&gt;<br />
&lt;/source&gt;<br />
<br />
Normally, PHP would put these in an array called &lt;code&gt;$_FILES&lt;/code&gt; that looked like:<br />
&lt;pre&gt;<br />
Array<br />
(<br />
[jform1] =&gt; Array<br />
(<br />
[name] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; youtube_icon.png<br />
[1] =&gt; Younger_Son_2.jpg<br />
)<br />
<br />
)<br />
<br />
[type] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; image/png<br />
[1] =&gt; image/jpeg<br />
)<br />
<br />
)<br />
<br />
[tmp_name] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; /tmp/phpXoIpSD<br />
[1] =&gt; /tmp/phpWDE7ye<br />
)<br />
<br />
)<br />
<br />
[error] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; 0<br />
[1] =&gt; 0<br />
)<br />
<br />
)<br />
<br />
[size] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; 34409<br />
[1] =&gt; 99529<br />
)<br />
<br />
)<br />
<br />
)<br />
<br />
)<br />
&lt;/pre&gt;<br />
<br />
JInputFiles produces a result that is cleaner and easier to work with:<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$files = $input-&gt;files-&gt;get('jform1');<br />
&lt;/source&gt;<br />
<br />
&lt;code&gt;$files&lt;/code&gt; then becomes:<br />
<br />
&lt;pre&gt;<br />
Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; Array<br />
(<br />
[name] =&gt; youtube_icon.png<br />
[type] =&gt; image/png<br />
[tmp_name] =&gt; /tmp/phpXoIpSD<br />
[error] =&gt; 0<br />
[size] =&gt; 34409<br />
)<br />
<br />
[1] =&gt; Array<br />
(<br />
[name] =&gt; Younger_Son_2.jpg<br />
[type] =&gt; image/jpeg<br />
[tmp_name] =&gt; /tmp/phpWDE7ye<br />
[error] =&gt; 0<br />
[size] =&gt; 99529<br />
)<br />
<br />
)<br />
<br />
)<br />
&lt;/pre&gt;<br />
<br />
In this way, the data from each file element is consolidated into a single array and can be indexed in a more straightforward manner.<br />
<br />
== Background ==<br />
<br />
This is based on an email discussion: [https://groups.google.com/d/msg/joomla-dev-framework/LbALkK1ifMo/5waSiIlb21gJ Framework List 23 July 2011]<br />
<br />
The idea behind JInput is to abstract out the input source to allow code to be reused in different applications and in different contexts. What I mean by this is that you could have a controller that grabs data from an input source. Instead of always getting it from the request (i.e. get and post variables), you get it from JInput. So say for instance you have a MVC triad in your component that is meant to get data from the browser as a client (a typical web application). Now suppose you want to reuse that same code but interface with it using JSON. Instead of rewriting your triad, you just extend JInput and have it grab it data from a parsed json object and perform any translation that you need to perform.<br />
<br />
The plan is to have JApplication instantiate JInput in its constructor. Then in your code you get the input object from the application and get your input from there. It will be a public property in Japplication so that it can be swapped out of that is appropriate.<br />
<br />
We get the added benefit that we get rid of the static JRequest which makes a whole bunch the code a whole lot easier to test because you can inject mock inputs directly instead of trying to fudge with hackish dependencies.<br />
<br />
The end result will be that your code will get the input object from the application (we will probably add something to JController at some point to make it more convenient to use there as well).<br />
<br />
Once you have your JInput object, you use it fairly in a fairly similar manner to how JRequest is used:<br />
$input-&gt;get('varname', 'default_value', 'filter');<br />
<br />
Where filter is a filter that is supported by JFilterInput. JInput::clean proxies to JFilter. We'll have to tweak JFilter a little bit so that it is more extensible. It defaults to cmd so that developers have to be intentional about things if they want to have more lenient filtering.<br />
<br />
There is also a getArray method that allows you to specify an array of key and filter pairs so that you can get a whole array of filtered input.<br />
<br />
If you want to get data from a specific super global array, you can do $input-&gt;get-&gt;get(...) or $input-&gt;post-&gt;get(...).<br />
<br />
JApplication is deprecated, Use JApplicationCms instead unless specified otherwise. JRequest is deprecated but will remain in the CMS through the 3.x series at a minimum. As such, it is easiest to still use JRequest with CMS applications. In the future get the JInput object from the application instead.<br />
<br />
&lt;noinclude&gt;<br />
[[Category:Tutorials]]<br />
[[Category:Development]]<br />
&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Retrieving_request_data_using_JInputRetrieving request data using JInput2015-09-05T17:53:19Z<p>Mvangeest: Adjusted version template</p>
<hr />
<div>{{version|2.5,3.x|platform=11.1,12.1}}<br />
==Requirements==<br />
To be able to use JInput as described here, you must be using Joomla 2.5.0 or above.<br />
<br />
Please note there are known issues with JInput and Magic Quotes (Deprecated in PHP 5.3.0 and removed in PHP 5.4.0). Most servers have these turned off - however it is important to bear this in mind whilst developing a component. For this reason all core components in Joomla 2.5.x still use JRequest. As of Joomla 3.0+ magic quotes is required to be disabled and thus this is no longer an issue.<br />
<br />
==Using JInput==<br />
To use JInput you must first create the object by using this code:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$jinput = JFactory::getApplication()-&gt;input;&lt;/source&gt;<br />
<br />
===Getting Values===<br />
To get a value from JInput, you can use:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;get('varname', 'default_value', 'filter');&lt;/source&gt;<br />
<br />
The filter defaults to &lt;code&gt;cmd&lt;/code&gt;.<br />
<br />
{{notice|The code fragments in the following list show the ''implementation'' of the filters (assuming the value you want to retrieve is stored in &lt;code&gt;$source&lt;/code&gt;). You do not need them to ''use'' JInput; all you need for using JInput is the code shown above.}}<br />
<br />
Available filters are:<br />
<br />
*INT<br />
*INTEGER<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Only use the first integer value<br />
preg_match('/-?[0-9]+/', (string) $source, $matches);<br />
$result = @ (int) $matches[0];<br />
&lt;/source&gt;<br />
*UINT<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Only use the first integer value<br />
preg_match('/-?[0-9]+/', (string) $source, $matches);<br />
$result = @ abs((int) $matches[0]);<br />
&lt;/source&gt;<br />
*FLOAT<br />
*DOUBLE<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Only use the first floating point value<br />
preg_match('/-?[0-9]+(\.[0-9]+)?/', (string) $source, $matches);<br />
$result = @ (float) $matches[0];<br />
&lt;/source&gt;<br />
*BOOL<br />
*BOOLEAN<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$result = (bool) $source;<br />
&lt;/source&gt;<br />
*WORD<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Only allow characters a-z, and underscores<br />
$result = (string) preg_replace('/[^A-Z_]/i', '', $source);<br />
&lt;/source&gt;<br />
*ALNUM<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Allow a-z and 0-9 only<br />
$result = (string) preg_replace('/[^A-Z0-9]/i', '', $source);<br />
&lt;/source&gt;<br />
*CMD<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Allow a-z, 0-9, underscore, dot, dash. Also remove leading dots from result. <br />
$result = (string) preg_replace('/[^A-Z0-9_\.-]/i', '', $source);<br />
$result = ltrim($result, '.');<br />
&lt;/source&gt;<br />
*BASE64<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Allow a-z, 0-9, slash, plus, equals.<br />
$result = (string) preg_replace('/[^A-Z0-9\/+=]/i', '', $source);<br />
&lt;/source&gt;<br />
*STRING<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Converts the input to a plain text string; strips all tags / attributes.<br />
$result = (string) $this-&gt;_remove($this-&gt;_decode((string) $source));<br />
&lt;/source&gt;<br />
*HTML<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Converts the input to a string; strips all HTML tags / attributes.<br />
$result = (string) $this-&gt;_remove($this-&gt;_decode((string) $source));<br />
&lt;/source&gt;<br />
*ARRAY<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Attempts to convert the input to an array.<br />
$result = (array) $source;<br />
&lt;/source&gt;<br />
*PATH<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Converts the input into a string and validates it as a path. (e.g. path/to/file.png or path/to/dir)<br />
// Note: Does NOT accept absolute paths, or paths ending in a trailing slash.<br />
// For a visual representation of the pattern matching used, see http://www.regexper.com/#^[A-Za-z0-9_-]%2B[A-Za-z0-9_\.-]*%28[\\\\\%2F][A-Za-z0-9_-]%2B[A-Za-z0-9_\.-]*%29*%24<br />
// Will return null if the input was invalid.<br />
$pattern = '/^[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*([\\\\\/][A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$/';<br />
preg_match($pattern, (string) $source, $matches);<br />
$result = @ (string) $matches[0];<br />
&lt;/source&gt;<br />
*RAW<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// The raw input. No sanitation provided.<br />
$result = $source;<br />
&lt;/source&gt;<br />
*USERNAME<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Strips all invalid username characters.<br />
$result = (string) preg_replace('/[\x00-\x1F\x7F&lt;&gt;&quot;\'%&amp;]/', '', $source)<br />
&lt;/source&gt;<br />
<br />
Alternatively instead of adding the filter you can use the JInput type specific methods:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Instead of:<br />
$input-&gt;get('name', '', 'STR');<br />
// you can use:<br />
$input-&gt;getString('name', '');<br />
<br />
// Instead of:<br />
$input-&gt;get('memberId', 0, 'INT');<br />
// you can use:<br />
$input-&gt;getInt('memberId', 0);<br />
&lt;/source&gt;<br />
<br />
===Getting Multiple Values===<br />
<br />
To retrieve a number of values you can use the &lt;code&gt;getArray()&lt;/code&gt; method:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$fooValues = $jinput-&gt;getArray(array('var1' =&gt; '', 'var2' =&gt; '', 'var3' =&gt; ''));<br />
&lt;/source&gt;<br />
<br />
or, if you want to determine the data to get step by step:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$fooArray = array();<br />
$fooArray['var1'] = '';<br />
$fooArray['var2'] = '';<br />
$fooArray['var3'] = '';<br />
$fooValues = $jinput-&gt;getArray($fooArray);<br />
&lt;/source&gt;<br />
<br />
The &lt;code&gt;$fooValues&lt;/code&gt; will be an array that consists of the same keys as used in &lt;code&gt;$fooArray&lt;/code&gt;, but with values attached.<br />
<br />
You can also specify different filters for each of the inputs:<br />
<br />
&lt;source lang=&quot;php&gt;<br />
$fooValues = $jinput-&gt;getArray(array(<br />
'var1' =&gt; 'int',<br />
'var2' =&gt; 'float',<br />
'var3' =&gt; 'word'<br />
));<br />
&lt;/source&gt;<br />
<br />
You can also nest arrays to get more complicated hierarchies of values:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$fooValues = $jinput-&gt;getArray(array(<br />
'jform' =&gt; array(<br />
'title' =&gt; 'string',<br />
'quantity' =&gt; 'int',<br />
'state' =&gt; 'int'<br />
)<br />
));<br />
&lt;/source&gt;<br />
<br />
===Getting Values from a Specific Super Global===<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;get-&gt;get('varname', 'default_value', 'filter');&lt;/source&gt;<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;post-&gt;get('varname', 'default_value', 'filter');&lt;/source&gt;<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;server-&gt;get('varname', 'default_value', 'filter');&lt;/source&gt;<br />
<br />
To retrieve an entire object, you can use:<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;get('varname', null, null);&lt;/source&gt;<br />
<br />
===Setting Values===<br />
<br />
To set a value via JInput, you can use:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$jinput-&gt;set('varname', $foo);&lt;/source&gt;<br />
<br />
===Retrieving File Data===<br />
<br />
The format that PHP returns file data in for arrays can at times be awkward, especially when dealing with arrays of files. JInputFiles provides a convenient interface for making life a little easier, grouping the data by file.<br />
<br />
Suppose you have a form like:<br />
&lt;source lang=&quot;html4strict&quot;&gt;<br />
&lt;form action=&quot;&lt;?php echo JRoute::_('index.php?option=com_example&amp;task=file.submit'); ?&gt;&quot; enctype=&quot;multipart/form-data&quot; method=&quot;post&quot;&gt;<br />
&lt;input type=&quot;file&quot; name=&quot;jform1[test][]&quot; /&gt;<br />
&lt;input type=&quot;file&quot; name=&quot;jform1[test][]&quot; /&gt;<br />
&lt;input type=&quot;submit&quot; value=&quot;submit&quot; /&gt;<br />
&lt;/form&gt;<br />
&lt;/source&gt;<br />
<br />
Normally, PHP would put these in an array called &lt;code&gt;$_FILES&lt;/code&gt; that looked like:<br />
&lt;pre&gt;<br />
Array<br />
(<br />
[jform1] =&gt; Array<br />
(<br />
[name] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; youtube_icon.png<br />
[1] =&gt; Younger_Son_2.jpg<br />
)<br />
<br />
)<br />
<br />
[type] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; image/png<br />
[1] =&gt; image/jpeg<br />
)<br />
<br />
)<br />
<br />
[tmp_name] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; /tmp/phpXoIpSD<br />
[1] =&gt; /tmp/phpWDE7ye<br />
)<br />
<br />
)<br />
<br />
[error] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; 0<br />
[1] =&gt; 0<br />
)<br />
<br />
)<br />
<br />
[size] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; 34409<br />
[1] =&gt; 99529<br />
)<br />
<br />
)<br />
<br />
)<br />
<br />
)<br />
&lt;/pre&gt;<br />
<br />
JInputFiles produces a result that is cleaner and easier to work with:<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$files = $input-&gt;files-&gt;get('jform1');<br />
&lt;/source&gt;<br />
<br />
&lt;code&gt;$files&lt;/code&gt; then becomes:<br />
<br />
&lt;pre&gt;<br />
Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; Array<br />
(<br />
[name] =&gt; youtube_icon.png<br />
[type] =&gt; image/png<br />
[tmp_name] =&gt; /tmp/phpXoIpSD<br />
[error] =&gt; 0<br />
[size] =&gt; 34409<br />
)<br />
<br />
[1] =&gt; Array<br />
(<br />
[name] =&gt; Younger_Son_2.jpg<br />
[type] =&gt; image/jpeg<br />
[tmp_name] =&gt; /tmp/phpWDE7ye<br />
[error] =&gt; 0<br />
[size] =&gt; 99529<br />
)<br />
<br />
)<br />
<br />
)<br />
&lt;/pre&gt;<br />
<br />
In this way, the data from each file element is consolidated into a single array and can be indexed in a more straightforward manner.<br />
<br />
== Background ==<br />
<br />
This is based on an email discussion: [https://groups.google.com/d/msg/joomla-dev-framework/LbALkK1ifMo/5waSiIlb21gJ Framework List 23 July 2011]<br />
<br />
The idea behind JInput is to abstract out the input source to allow code to be reused in different applications and in different contexts. What I mean by this is that you could have a controller that grabs data from an input source. Instead of always getting it from the request (i.e. get and post variables), you get it from JInput. So say for instance you have a MVC triad in your component that is meant to get data from the browser as a client (a typical web application). Now suppose you want to reuse that same code but interface with it using JSON. Instead of rewriting your triad, you just extend JInput and have it grab it data from a parsed json object and perform any translation that you need to perform.<br />
<br />
The plan is to have JApplication instantiate JInput in its constructor. Then in your code you get the input object from the application and get your input from there. It will be a public property in Japplication so that it can be swapped out of that is appropriate.<br />
<br />
We get the added benefit that we get rid of the static JRequest which makes a whole bunch the code a whole lot easier to test because you can inject mock inputs directly instead of trying to fudge with hackish dependencies.<br />
<br />
The end result will be that your code will get the input object from the application (we will probably add something to JController at some point to make it more convenient to use there as well).<br />
<br />
Once you have your JInput object, you use it fairly in a fairly similar manner to how JRequest is used:<br />
$input-&gt;get('varname', 'default_value', 'filter');<br />
<br />
Where filter is a filter that is supported by JFilterInput. JInput::clean proxies to JFilter. We'll have to tweak JFilter a little bit so that it is more extensible. It defaults to cmd so that developers have to be intentional about things if they want to have more lenient filtering.<br />
<br />
There is also a getArray method that allows you to specify an array of key and filter pairs so that you can get a whole array of filtered input.<br />
<br />
If you want to get data from a specific super global array, you can do $input-&gt;get-&gt;get(...) or $input-&gt;post-&gt;get(...).<br />
<br />
JApplication is deprecated, Use JApplicationCms instead unless specified otherwise. JRequest is deprecated but will remain in the CMS through the 3.x series at a minimum. As such, it is easiest to still use JRequest with CMS applications. In the future get the JInput object from the application instead.<br />
<br />
&lt;noinclude&gt;<br />
[[Category:Tutorials]]<br />
[[Category:Development]]<br />
&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Retrieving_request_data_using_JInputRetrieving request data using JInput2015-09-05T17:33:59Z<p>Mvangeest: Added clarification after user request</p>
<hr />
<div>{{version|2.5,3.1|platform=11.1,12.1}}<br />
<br />
==Requirements==<br />
To be able to use JInput as described here, you must be using Joomla 2.5.0 or above.<br />
<br />
Please note there are known issues with JInput and Magic Quotes (Deprecated in PHP 5.3.0 and removed in PHP 5.4.0). Most servers have these turned off - however it is important to bear this in mind whilst developing a component. For this reason all core components in Joomla 2.5.x still use JRequest. As of Joomla 3.0+ magic quotes is required to be disabled and thus this is no longer an issue.<br />
<br />
==Using JInput==<br />
To use JInput you must first create the object by using this code:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$jinput = JFactory::getApplication()-&gt;input;&lt;/source&gt;<br />
<br />
===Getting Values===<br />
To get a value from JInput, you can use:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;get('varname', 'default_value', 'filter');&lt;/source&gt;<br />
<br />
The filter defaults to &lt;code&gt;cmd&lt;/code&gt;.<br />
<br />
{{notice|The code fragments in the following list show the ''implementation'' of the filters (assuming the value you want to retrieve is stored in &lt;code&gt;$source&lt;/code&gt;). You do not need them to ''use'' JInput; all you need for using JInput is the code shown above.}}<br />
<br />
Available filters are:<br />
<br />
*INT<br />
*INTEGER<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Only use the first integer value<br />
preg_match('/-?[0-9]+/', (string) $source, $matches);<br />
$result = @ (int) $matches[0];<br />
&lt;/source&gt;<br />
*UINT<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Only use the first integer value<br />
preg_match('/-?[0-9]+/', (string) $source, $matches);<br />
$result = @ abs((int) $matches[0]);<br />
&lt;/source&gt;<br />
*FLOAT<br />
*DOUBLE<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Only use the first floating point value<br />
preg_match('/-?[0-9]+(\.[0-9]+)?/', (string) $source, $matches);<br />
$result = @ (float) $matches[0];<br />
&lt;/source&gt;<br />
*BOOL<br />
*BOOLEAN<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$result = (bool) $source;<br />
&lt;/source&gt;<br />
*WORD<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Only allow characters a-z, and underscores<br />
$result = (string) preg_replace('/[^A-Z_]/i', '', $source);<br />
&lt;/source&gt;<br />
*ALNUM<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Allow a-z and 0-9 only<br />
$result = (string) preg_replace('/[^A-Z0-9]/i', '', $source);<br />
&lt;/source&gt;<br />
*CMD<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Allow a-z, 0-9, underscore, dot, dash. Also remove leading dots from result. <br />
$result = (string) preg_replace('/[^A-Z0-9_\.-]/i', '', $source);<br />
$result = ltrim($result, '.');<br />
&lt;/source&gt;<br />
*BASE64<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Allow a-z, 0-9, slash, plus, equals.<br />
$result = (string) preg_replace('/[^A-Z0-9\/+=]/i', '', $source);<br />
&lt;/source&gt;<br />
*STRING<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Converts the input to a plain text string; strips all tags / attributes.<br />
$result = (string) $this-&gt;_remove($this-&gt;_decode((string) $source));<br />
&lt;/source&gt;<br />
*HTML<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Converts the input to a string; strips all HTML tags / attributes.<br />
$result = (string) $this-&gt;_remove($this-&gt;_decode((string) $source));<br />
&lt;/source&gt;<br />
*ARRAY<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Attempts to convert the input to an array.<br />
$result = (array) $source;<br />
&lt;/source&gt;<br />
*PATH<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Converts the input into a string and validates it as a path. (e.g. path/to/file.png or path/to/dir)<br />
// Note: Does NOT accept absolute paths, or paths ending in a trailing slash.<br />
// For a visual representation of the pattern matching used, see http://www.regexper.com/#^[A-Za-z0-9_-]%2B[A-Za-z0-9_\.-]*%28[\\\\\%2F][A-Za-z0-9_-]%2B[A-Za-z0-9_\.-]*%29*%24<br />
// Will return null if the input was invalid.<br />
$pattern = '/^[A-Za-z0-9_-]+[A-Za-z0-9_\.-]*([\\\\\/][A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$/';<br />
preg_match($pattern, (string) $source, $matches);<br />
$result = @ (string) $matches[0];<br />
&lt;/source&gt;<br />
*RAW<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// The raw input. No sanitation provided.<br />
$result = $source;<br />
&lt;/source&gt;<br />
*USERNAME<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Strips all invalid username characters.<br />
$result = (string) preg_replace('/[\x00-\x1F\x7F&lt;&gt;&quot;\'%&amp;]/', '', $source)<br />
&lt;/source&gt;<br />
<br />
Alternatively instead of adding the filter you can use the JInput type specific methods:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
// Instead of:<br />
$input-&gt;get('name', '', 'STR');<br />
// you can use:<br />
$input-&gt;getString('name', '');<br />
<br />
// Instead of:<br />
$input-&gt;get('memberId', 0, 'INT');<br />
// you can use:<br />
$input-&gt;getInt('memberId', 0);<br />
&lt;/source&gt;<br />
<br />
===Getting Multiple Values===<br />
<br />
To retrieve a number of values you can use the &lt;code&gt;getArray()&lt;/code&gt; method:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$fooValues = $jinput-&gt;getArray(array('var1' =&gt; '', 'var2' =&gt; '', 'var3' =&gt; ''));<br />
&lt;/source&gt;<br />
<br />
or, if you want to determine the data to get step by step:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$fooArray = array();<br />
$fooArray['var1'] = '';<br />
$fooArray['var2'] = '';<br />
$fooArray['var3'] = '';<br />
$fooValues = $jinput-&gt;getArray($fooArray);<br />
&lt;/source&gt;<br />
<br />
The &lt;code&gt;$fooValues&lt;/code&gt; will be an array that consists of the same keys as used in &lt;code&gt;$fooArray&lt;/code&gt;, but with values attached.<br />
<br />
You can also specify different filters for each of the inputs:<br />
<br />
&lt;source lang=&quot;php&gt;<br />
$fooValues = $jinput-&gt;getArray(array(<br />
'var1' =&gt; 'int',<br />
'var2' =&gt; 'float',<br />
'var3' =&gt; 'word'<br />
));<br />
&lt;/source&gt;<br />
<br />
You can also nest arrays to get more complicated hierarchies of values:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$fooValues = $jinput-&gt;getArray(array(<br />
'jform' =&gt; array(<br />
'title' =&gt; 'string',<br />
'quantity' =&gt; 'int',<br />
'state' =&gt; 'int'<br />
)<br />
));<br />
&lt;/source&gt;<br />
<br />
===Getting Values from a Specific Super Global===<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;get-&gt;get('varname', 'default_value', 'filter');&lt;/source&gt;<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;post-&gt;get('varname', 'default_value', 'filter');&lt;/source&gt;<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;server-&gt;get('varname', 'default_value', 'filter');&lt;/source&gt;<br />
<br />
To retrieve an entire object, you can use:<br />
&lt;source lang=&quot;php&quot;&gt;$foo = $jinput-&gt;get('varname', null, null);&lt;/source&gt;<br />
<br />
===Setting Values===<br />
<br />
To set a value via JInput, you can use:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$jinput-&gt;set('varname', $foo);&lt;/source&gt;<br />
<br />
===Retrieving File Data===<br />
<br />
The format that PHP returns file data in for arrays can at times be awkward, especially when dealing with arrays of files. JInputFiles provides a convenient interface for making life a little easier, grouping the data by file.<br />
<br />
Suppose you have a form like:<br />
&lt;source lang=&quot;html4strict&quot;&gt;<br />
&lt;form action=&quot;&lt;?php echo JRoute::_('index.php?option=com_example&amp;task=file.submit'); ?&gt;&quot; enctype=&quot;multipart/form-data&quot; method=&quot;post&quot;&gt;<br />
&lt;input type=&quot;file&quot; name=&quot;jform1[test][]&quot; /&gt;<br />
&lt;input type=&quot;file&quot; name=&quot;jform1[test][]&quot; /&gt;<br />
&lt;input type=&quot;submit&quot; value=&quot;submit&quot; /&gt;<br />
&lt;/form&gt;<br />
&lt;/source&gt;<br />
<br />
Normally, PHP would put these in an array called &lt;code&gt;$_FILES&lt;/code&gt; that looked like:<br />
&lt;pre&gt;<br />
Array<br />
(<br />
[jform1] =&gt; Array<br />
(<br />
[name] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; youtube_icon.png<br />
[1] =&gt; Younger_Son_2.jpg<br />
)<br />
<br />
)<br />
<br />
[type] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; image/png<br />
[1] =&gt; image/jpeg<br />
)<br />
<br />
)<br />
<br />
[tmp_name] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; /tmp/phpXoIpSD<br />
[1] =&gt; /tmp/phpWDE7ye<br />
)<br />
<br />
)<br />
<br />
[error] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; 0<br />
[1] =&gt; 0<br />
)<br />
<br />
)<br />
<br />
[size] =&gt; Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; 34409<br />
[1] =&gt; 99529<br />
)<br />
<br />
)<br />
<br />
)<br />
<br />
)<br />
&lt;/pre&gt;<br />
<br />
JInputFiles produces a result that is cleaner and easier to work with:<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$files = $input-&gt;files-&gt;get('jform1');<br />
&lt;/source&gt;<br />
<br />
&lt;code&gt;$files&lt;/code&gt; then becomes:<br />
<br />
&lt;pre&gt;<br />
Array<br />
(<br />
[test] =&gt; Array<br />
(<br />
[0] =&gt; Array<br />
(<br />
[name] =&gt; youtube_icon.png<br />
[type] =&gt; image/png<br />
[tmp_name] =&gt; /tmp/phpXoIpSD<br />
[error] =&gt; 0<br />
[size] =&gt; 34409<br />
)<br />
<br />
[1] =&gt; Array<br />
(<br />
[name] =&gt; Younger_Son_2.jpg<br />
[type] =&gt; image/jpeg<br />
[tmp_name] =&gt; /tmp/phpWDE7ye<br />
[error] =&gt; 0<br />
[size] =&gt; 99529<br />
)<br />
<br />
)<br />
<br />
)<br />
&lt;/pre&gt;<br />
<br />
In this way, the data from each file element is consolidated into a single array and can be indexed in a more straightforward manner.<br />
<br />
== Background ==<br />
<br />
This is based on an email discussion: [https://groups.google.com/d/msg/joomla-dev-framework/LbALkK1ifMo/5waSiIlb21gJ Framework List 23 July 2011]<br />
<br />
The idea behind JInput is to abstract out the input source to allow code to be reused in different applications and in different contexts. What I mean by this is that you could have a controller that grabs data from an input source. Instead of always getting it from the request (i.e. get and post variables), you get it from JInput. So say for instance you have a MVC triad in your component that is meant to get data from the browser as a client (a typical web application). Now suppose you want to reuse that same code but interface with it using JSON. Instead of rewriting your triad, you just extend JInput and have it grab it data from a parsed json object and perform any translation that you need to perform.<br />
<br />
The plan is to have JApplication instantiate JInput in its constructor. Then in your code you get the input object from the application and get your input from there. It will be a public property in Japplication so that it can be swapped out of that is appropriate.<br />
<br />
We get the added benefit that we get rid of the static JRequest which makes a whole bunch the code a whole lot easier to test because you can inject mock inputs directly instead of trying to fudge with hackish dependencies.<br />
<br />
The end result will be that your code will get the input object from the application (we will probably add something to JController at some point to make it more convenient to use there as well).<br />
<br />
Once you have your JInput object, you use it fairly in a fairly similar manner to how JRequest is used:<br />
$input-&gt;get('varname', 'default_value', 'filter');<br />
<br />
Where filter is a filter that is supported by JFilterInput. JInput::clean proxies to JFilter. We'll have to tweak JFilter a little bit so that it is more extensible. It defaults to cmd so that developers have to be intentional about things if they want to have more lenient filtering.<br />
<br />
There is also a getArray method that allows you to specify an array of key and filter pairs so that you can get a whole array of filtered input.<br />
<br />
If you want to get data from a specific super global array, you can do $input-&gt;get-&gt;get(...) or $input-&gt;post-&gt;get(...).<br />
<br />
JApplication is deprecated, Use JApplicationCms instead unless specified otherwise. JRequest is deprecated but will remain in the CMS through the 3.x series at a minimum. As such, it is easiest to still use JRequest with CMS applications. In the future get the JInput object from the application instead.<br />
<br />
&lt;noinclude&gt;<br />
[[Category:Tutorials]]<br />
[[Category:Development]]<br />
&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Magic_quotes_and_securityMagic quotes and security2015-03-10T14:54:36Z<p>Mvangeest: Adjusted layout</p>
<hr />
<div>{{version|2.5,3.x}}<br />
'''Magic Quotes''' was a PHP feature, enabled using the &lt;code&gt;magic_quotes_gpc&lt;/code&gt; setting, that escaped (in a very limited way) most of the input data accessible to PHP scripts. It has been removed from PHP for [http://php.net/manual/en/security.magicquotes.whynot.php a variety of reasons]. For more on Magic Quotes, see [http://php.net/magic_quotes PHP Manual, Chapter 31. Magic Quotes].<br />
<br />
This PHP feature has been '''deprecated''' as of PHP 5.3.0 (30-06-2009) and has been '''removed''' from PHP as of PHP 5.4.0.<br />
<br />
: {{JVer|3.x}} Joomla! 3.0 and above requires &lt;code&gt;magic_quotes_gpc&lt;/code&gt; to be set to '''off''' and will not install if &lt;code&gt;magic_quotes_gpc&lt;/code&gt; is on.<br />
: {{JVer|2.5}} Joomla! 2.5 advises &lt;code&gt;magic_quotes_gpc&lt;/code&gt; to be set to '''off'''.<br />
<br />
JRequest automatically takes into account the setting of &lt;code&gt;magic_quotes_gpc&lt;/code&gt; and adjusts accordingly. If developers are using JRequest to request input then the actual value of the setting doesn't matter. If developers aren't using it then they will have to take the setting of &lt;code&gt;magic_quotes_gpc&lt;/code&gt; into account (for this reason it is still common practice for developers to use JRequest in Joomla 2.5 - even though it is deprecated).<br />
<br />
JInput does not take this into account. However, due to Joomla 3.x and higher requiring that magic quotes are disabled, this is no longer a problem.<br />
<br />
&lt;!-- KEEP THIS AT THE END OF THE PAGE --&gt;<br />
[[Category:Security Checklist]]</div>Mvangeest//docs.joomla.org/Magic_quotes_and_securityMagic quotes and security2015-03-10T14:52:23Z<p>Mvangeest: Fixed minor issues</p>
<hr />
<div>{{version|2.5,3.x}}<br />
<br />
'''Magic Quotes''' was a PHP feature, enabled using the &lt;code&gt;magic_quotes_gpc&lt;/code&gt; setting, that escaped (in a very limited way) most of the input data accessible to PHP scripts. It has been removed from PHP for [http://php.net/manual/en/security.magicquotes.whynot.php a variety of reasons]. For more on Magic Quotes, see [http://php.net/magic_quotes PHP Manual, Chapter 31. Magic Quotes].<br />
<br />
'''''This PHP feature has been deprecated as of PHP 5.3.0 (30-06-2009) and has been removed from PHP as of PHP 5.4.0.'''''<br />
<br />
: {{JVer|3.x}} Joomla! 3.0 and above requires &lt;code&gt;magic_quotes_gpc&lt;/code&gt; to be set to '''off''' and will not install if &lt;code&gt;magic_quotes_gpc&lt;/code&gt; is on.<br />
: {{JVer|2.5}} Joomla! 2.5 advises &lt;code&gt;magic_quotes_gpc&lt;/code&gt; to be set to '''off'''.<br />
<br />
JRequest automatically takes into account the setting of &lt;code&gt;magic_quotes_gpc&lt;/code&gt; and adjusts accordingly. If developers are using JRequest to request input then the actual value of the setting doesn't matter. If developers aren't using it then they will have to take the setting of &lt;code&gt;magic_quotes_gpc&lt;/code&gt; into account (for this reason it is still common practice for developers to use JRequest in Joomla 2.5 - even though it is deprecated).<br />
<br />
JInput does not take this into account. However, due to Joomla 3.x and higher requiring that magic quotes are disabled, this is no longer a problem.<br />
<br />
&lt;!-- KEEP THIS AT THE END OF THE PAGE --&gt;<br />
[[Category:Security Checklist]]</div>Mvangeest//docs.joomla.org/Supporting_SEF_URLs_in_your_componentSupporting SEF URLs in your component2015-03-01T20:43:37Z<p>Mvangeest: Fixed minor issues</p>
<hr />
<div>{{version/tutor|2.5,3.1}}<br />
{{:Search Engine Friendly URLs/en}}<br />
In Joomla!, each [[component]] is responsible for handling its own SEF URLs. Therefore, as the [[Developers|developer]] of a component, you will have to create your own '''router''' to allow your component to use SEF URLs.<br />
<br />
'''''{{JVer|3.3}} Note:''''' Since Joomla 3.3, one should rather implement the interface &lt;code&gt;[https://api.joomla.org/cms-3/classes/JComponentRouterInterface.html JComponentRouterInterface]&lt;/code&gt; and handle the routing and parsing similar as below, but via the methods of this interface. This will also evade the now fixed [https://github.com/joomla/joomla-cms/issues/5579 one way dash-to-colon issue].<br />
<br />
== The Concept ==<br />
<br />
Assuming you are following standard development practices, your component is probably using &quot;system URLs&quot; that look a lot like &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;, and your goal is to transform this into &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;. As the developer, you have two tasks: signalling the system that certain pieces of text are URLs and need to be transformed, and explaining the system how to transform URLs.<br />
<br />
=== Applying &lt;code&gt;JRoute::_&lt;/code&gt; ===<br />
<br />
It is difficult and inefficient for Joomla! to figure out which parts of your component's output are URLs. To support SEF URLs, you will need to change URL-generating code so that it applies &lt;code&gt;JRoute::_&lt;/code&gt; before outputting the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
echo JRoute::_('index.php?view=article&amp;id=1&amp;catid=20');<br />
&lt;/source&gt;<br />
<br />
Notice that it is possible to leave out the parameters &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;Itemid&lt;/code&gt;. &lt;code&gt;option&lt;/code&gt; defaults to the name of the component currently being executed, and &lt;code&gt;Itemid&lt;/code&gt; defaults to the current menu item's ID.<br />
<br />
In general, you should only apply this to URLs that users and/or search engines are able to see. For example, there is no need to transform URLs used in redirects that immediately result in other redirects.<br />
<br />
If the user turns off SEF URLs in the site's settings, &lt;code&gt;JRoute::_&lt;/code&gt; will produce working non-SEF URLs without any changes to the code.<br />
<br />
=== Writing a router ===<br />
<br />
You'll also need to write a router, which is a single file with two functions that convert system URLs to and from SEF URLs. This file needs to be placed at &lt;tt&gt;/components/com_yourcomponent/router.php&lt;/tt&gt;.<br />
<br />
The first function, &lt;code&gt;[componentname]BuildRoute(&amp;$query)&lt;/code&gt;, must transform an array of URL parameters into an array of segments that will form the SEF URL. Schematically, the transformation works as follows:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; &lt;code&gt;JRoute::_&lt;/code&gt;, called by your component or any other extension<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentBuildRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal route building (for display)<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
The second function, &lt;code&gt;[componentname]ParseRoute($segments)&lt;/code&gt;, must transform an array of segments back into an array of URL parameters. Schematically:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal route parsing<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentParseRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
The two functions must cooperate in such a way that the original URL can be reconstructed. You can think of &lt;code&gt;BuildRoute&lt;/code&gt; as a form of [[wikipedia:Encoding|encoding]] and &lt;code&gt;ParseRoute&lt;/code&gt; as the corresponding decoding. When the original URL isn't properly reproduced, your component will stop working.<br />
<br />
== Preparing Your Data for Routing ==<br />
<br />
Clearly, any URL format needs to contain some kind of information that identifies the data you want to show. If your system URLs look like &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;, that information is currently the &lt;tt&gt;id&lt;/tt&gt; URL parameter (&lt;tt&gt;id=1&lt;/tt&gt;). You probably want your SEF URLs to contain a textual description of the data they point to. In Joomla!, this is usually done by giving your users a way to enter an '''alias''' to be used in the URL.<br />
<br />
=== The Alias ===<br />
<br />
Even if your users can enter an alias, they might not do so, leaving the generation of a sensible alias up to your component. If your data has a title field, you can use that as a candidate for the alias (like the core [[Content]] component does).<br />
<br />
Considering that the alias will be used in URLs, it has to be URL safe. Joomla! provides a method making arbitrary strings URI safe, which includes replacing accented UTF­8 characters by their ASCII­7 equivalents, white spaces by hyphens, etc. Whether the user entered the alias or a candidate has been chosen automatically, you should ensure that the above requirements for a URL safe alias are met. A good place for implementing this, if you are using &lt;code&gt;JTable&lt;/code&gt;, is the &lt;code&gt;JTable::check()&lt;/code&gt; method, which is called during the save process. Have a look at this example code:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function check()<br />
{<br />
jimport('joomla.filter.output');<br />
if (empty($this-&gt;alias))<br />
{<br />
$this-&gt;alias = $this-&gt;title;<br />
}<br />
$this-&gt;alias = JFilterOutput::stringURLSafe($this-&gt;alias);<br />
<br />
/* All your other checks */<br />
return true;<br />
}<br />
&lt;/source&gt;<br />
<br />
If the alias field is empty the title is used as alias. Then the alias is made URL safe using the &lt;code&gt;JFilterOutput::stringURLSafe()&lt;/code&gt; method.<br />
<br />
=== The Slug ===<br />
<br />
A '''slug''' is used to minimise the amount of code you need to support SEF URLs. It consists of the numerical identifier (&lt;tt&gt;id&lt;/tt&gt;) your system URLs used, a colon (&lt;tt&gt;:&lt;/tt&gt;), and the alias you created as described above. <br />
<br />
Consider a SEF URL for an [[Article]] with &lt;tt&gt;id&lt;/tt&gt; 1 and title &quot;Welcome to Joomla!&quot;. The automatically generated alias for this article is &lt;tt&gt;welcome-to-joomla&lt;/tt&gt;, and the slug becomes &lt;tt&gt;1­:welcome­-to­-joomla&lt;/tt&gt;. In the [[Content]] component, the two elements are combined during the database query in the model (&lt;code&gt;a&lt;/code&gt; represents &lt;code&gt;#__content&lt;/code&gt;):<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$query = 'SELECT a.*, '.<br />
'CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(&quot;:&quot;, a.id, a.alias) ELSE a.id END as slug,'<br />
/*...*/;&lt;/source&gt;<br />
<br />
The advantage of this method of creating a slug is that you can simply use the slug as a drop-in replacement for the id in most places. For example, you don't need to check for and remove the colon and the alias from the request data manually: if you use [[Retrieving request data using JInput|JInput]]'s &lt;code&gt;int&lt;/code&gt; (integer) filter, it will do that automatically.<br />
<br />
== Routing URLs ==<br />
<br />
The &lt;code&gt;JRoute::_&lt;/code&gt; method translates the internal Joomla! URL to a custom URL. &lt;code&gt;JRoute::_&lt;/code&gt; has three parameters and its prototype is:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_($url, $xhtml = true, $ssl = null);&lt;/source&gt;<br />
<br />
Where:<br />
<br />
* &lt;code&gt;$url&lt;/code&gt; is a string containing the absolute or relative internal Joomla! URL.<br />
* &lt;code&gt;$xhtml&lt;/code&gt; is a boolean value that specifies whether or not the output should be in XHTML. This parameter is optional and if omitted defaults to true.<br />
* &lt;code&gt;$ssl&lt;/code&gt; is an integer value that specifies whether the URI should be secure. It should be set to 1 to force the URI to be secure using the global secure site URI, 0 to leave it in the same state as when it was passed, and -1 to force the URI to be unsecure using the global unsecure site URI.<br />
<br />
The most important parameter is &lt;code&gt;$url&lt;/code&gt;. A call to this method might look like:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_('index.php?view=article&amp;id=' . $row-&gt;slug);&lt;/source&gt;<br />
<br />
&lt;code&gt;$row-­&gt;slug&lt;/code&gt; is the value that was generated in step 2 from a combination of id and title alias.<br />
<br />
Another advantage of using &lt;code&gt;JRoute::_&lt;/code&gt; is that the router now handles &lt;code&gt;$option&lt;/code&gt; (the component name) and the &lt;code&gt;$Itemid&lt;/code&gt; (the menu item ID). The component itself doesn't have to know its name (&lt;code&gt;$option&lt;/code&gt;) or the active menu item (&lt;code&gt;$Itemid&lt;/code&gt;) like it did in previous version of Joomla!.<br />
<br />
It is important that you think about the sequence of the URL parameter in this stage. This will be more clear when we have a deeper look at the &lt;tt&gt;router.php&lt;/tt&gt; in the next section.<br />
<br />
The building process of JRouter is divided into two steps:<br />
<br />
* Create the application route. The application route is fully handled by JRouter and the component developer doesn’t have to do anything to make it work.<br />
* Create the component route. To create the component route, JRouter looks for the &lt;tt&gt;router.php&lt;/tt&gt; in the component directory which is responsible for building the route for the component.<br />
<br />
== The Component Router ==<br />
<br />
We will have two functions in the &lt;tt&gt;router.php&lt;/tt&gt;. One is responsible for building the URL and the other is responsible for parsing it. In the next examples, a very basic and a more advanced one, we assume that we have three views that links can point to. The first is a categories overview (&lt;code&gt;view=categories&lt;/code&gt;), the second is a single category (&lt;code&gt;view=category&lt;/code&gt;) and the third is a single article (&lt;code&gt;view=article&lt;/code&gt;).<br />
<br />
The file &lt;tt&gt;router.php&lt;/tt&gt; should be in the site area of your component. It is not used on admin/backend pages. Don't forget to add it to your XML [[Manifest files|manifest file]] in the site folder.<br />
<br />
=== A Simple Example ===<br />
<br />
This simple example will illustrate the basics of implementing a router for your component.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if (isset($query['view']))<br />
{<br />
$segments[] = $query['view'];<br />
unset($query['view']);<br />
}<br />
if (isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset($query['id']);<br />
};<br />
return $segments;<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
&lt;code&gt;JRouter&lt;/code&gt; passes a &lt;code&gt;$query&lt;/code&gt; array to the &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; function. This function will add the relevant parts of the array to the $segments array in the right order and will return the properly ordered array. The content of the &lt;code&gt;$query&lt;/code&gt; array needs to be unset, otherwise &lt;code&gt;JRouter&lt;/code&gt; will add it to the URL in the form of a query string (i.e. any variables that are not handled by the router will be passed in the query string).<br />
<br />
The prefix ''componentname'' is the name for your component, as found in the directory holding the component's files. For instance, a component &quot;Magic&quot; in directory &lt;tt&gt;/components/com_magic/...&lt;/tt&gt; would use a prefix &lt;code&gt;magic&lt;/code&gt; (all lower case).<br />
<br />
The next function in the &lt;tt&gt;router.php&lt;/tt&gt; parses the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute($segments)<br />
{<br />
$vars = array();<br />
switch($segments[0])<br />
{<br />
case 'categories':<br />
$vars['view'] = 'categories';<br />
break;<br />
case 'category':<br />
$vars['view'] = 'category';<br />
$id = explode(':', $segments[1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'article':<br />
$vars['view'] = 'article';<br />
$id = explode(':', $segments[1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
What happens here? In the function &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; we arranged the items in the &lt;code&gt;$query&lt;/code&gt; array in a specific sequence. This means that in this example the view is first and the id is second in the array.<br />
<br />
By reading &lt;code&gt;$segments[0]&lt;/code&gt;, we access the name of the view. We set the right view and/or identifier depending on its value and we return the &lt;code&gt;$vars&lt;/code&gt; array to &lt;code&gt;JRouter&lt;/code&gt;. &lt;code&gt;$vars&lt;/code&gt; should be an associative array similar to the array that was passed to the BuildRoute method.<br />
<br />
The above example of the &lt;tt&gt;router.php&lt;/tt&gt; is a very simple way to generate SEF URLs but should show how this works quite clearly.<br />
<br />
The generated URL in this example contains the name of the view and doesn't reflect the content hierarchy:<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[view]/[slug]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
=== A More Advanced Example ===<br />
<br />
In the next example we will try to get rid of the need for the view and we will try to reflect the current hierarchy level in the URL.<br />
<br />
The goal is URL's that look like:<br />
<br />
* When viewing an article: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]/[article]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing a category: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing the categories overview: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
Let's assume we have done step 1 and 2 also for the category.<br />
<br />
The link to the article would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_('index.php?view=article&amp;catid=' . $row-­&gt;catslug . '&amp;id='.$row-­&gt;slug);<br />
&lt;/source&gt;<br />
<br />
And the Link to the category would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_('index.php?view=category&amp;id=' . $row-&gt;catslug);<br />
&lt;/source&gt;<br />
<br />
The corresponding &lt;tt&gt;router.php&lt;/tt&gt;:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function [componentname]BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if (isset($query['catid']))<br />
{<br />
$segments[] = $query['catid'];<br />
unset($query['catid']);<br />
};<br />
if (isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset($query['id']);<br />
};<br />
unset($query['view']);<br />
return $segments;<br />
}<br />
&lt;/source&gt;<br />
<br />
The difference now is that we don’t add the name of the view to the &lt;code&gt;$segments&lt;/code&gt; array. We still unset the view key since otherwise, &lt;code&gt;JRouter&lt;/code&gt; would add it to the URL as part of the query string. Another new thing here is the additional parameter catid that we push into the &lt;code&gt;$segments&lt;/code&gt; array.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute($segments)<br />
{<br />
$vars = array();<br />
$app = JFactory::getApplication();<br />
$menu = $app-&gt;getMenu();<br />
$item = $menu-&gt;getActive();<br />
// Count segments<br />
$count = count($segments);<br />
// Handle View and Identifier<br />
switch ($item-&gt;query['view'])<br />
{<br />
case 'categories':<br />
if ($count == 1)<br />
{<br />
$vars['view'] = 'category';<br />
}<br />
if ($count == 2)<br />
{<br />
$vars['view'] = 'article';<br />
}<br />
$id = explode(':', $segments[$count-1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'category':<br />
$id = explode(':', $segments[$count-1]);<br />
$vars['id'] = (int) $id[0];<br />
$vars['view'] = 'article';<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
You can see that this ParseRoute function has a lot of different code parts in comparison to the previous. The reason for this is simple. We don’t have the name of the view in the &lt;code&gt;$segments&lt;/code&gt; array and we need to find another way to determine it.<br />
<br />
We need to find out which level of hierarchy we are in by receiving the root element. We do this by looking to the view name of the active menu item:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$item-­&gt;query['view']<br />
&lt;/source&gt;<br />
<br />
Also we need to know the number of items in the &lt;code&gt;$segments&lt;/code&gt; array:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$count = count($segments);<br />
&lt;/source&gt;<br />
<br />
With this information we can correctly set the view for all possible three cases:<br />
<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has two items (&lt;code&gt;$catid&lt;/code&gt; and &lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to an article.<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has one item (&lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to a category.<br />
* The menu item is a link to a category. In this case, we know that any item in the &lt;code&gt;$segments&lt;/code&gt; array is the identifier for an article.<br />
<br />
The result of all this code is clean and human-readable component URLs.<br />
<br />
== Routers and Menu Items ==<br />
<br />
A last important part of creating a router is considering what to do with menu items. As explained on [[Search Engine Friendly URLs]], the output of the component router is used ''after'' the first segment of a route, the first segment being the menu item's alias. This creates a difficult question: how is your router and/or other code to know which menu item to route through?<br />
<br />
Suppose, for example, that your component is currently producing output for the page &lt;tt&gt;/dogs&lt;/tt&gt;, which lists all dogs in the system. Of course, the items in the list need to be links to pages that display more details about one dog. What should the URL to the dog with ID 21 and name Fido become? Using a router that works according to the principles we've seen so far, the route that is produced is &lt;tt&gt;dogs/21-fido&lt;/tt&gt;, or with some additional work &lt;tt&gt;/dogs/fido&lt;/tt&gt;. But perhaps the user has created a menu item with the alias &lt;tt&gt;mydoggy&lt;/tt&gt; which displays exactly that dog's details. Then it is probably the user's intention to route this URL through that menu item, and the item in the list should link to the page &lt;tt&gt;/mydoggy&lt;/tt&gt;.<br />
<br />
More generally, whenever you are building a route, you will need to find the menu item that is most suitable as a ''starting point'' for building your route. The term ''starting point'' is emphasized because the rest of the route depends on the configuration of the menu item. In our example above, &lt;tt&gt;/dogs/21-fido&lt;/tt&gt; is an acceptable route, &lt;tt&gt;/mydoggy&lt;/tt&gt; is arguably even better, but &lt;tt&gt;/mydoggy/21-fido&lt;/tt&gt; is simply wrong, since &lt;tt&gt;/mydoggy&lt;/tt&gt; is in itself a menu item that is set up to display &lt;tt&gt;fido&lt;/tt&gt;'s information.<br />
<br />
Several approaches are available to tackle this problem. Joomla!'s core components take a mixed approach, separating responsibilities in two units of code: the router itself and the so-called &lt;code&gt;[componentname]RouteHelper&lt;/code&gt;. The &lt;code&gt;[componentname]RouteHelper&lt;/code&gt; provides methods that find the most suitable menu item for a given piece of data to be displayed, while the router analyzes the menu item and puts any information that is not determined by the menu item's configuration into the route. This does mean that the ''calling code'' must explicitly call the helper's method before routing (&lt;code&gt;echo JRoute::_(DogsRouteHelper::getDogRoute(21));&lt;/code&gt;).<br />
<br />
== See Also ==<br />
<br />
There is a useful thread on this subject here: [[jtopic:148632]] (note, may be out of date)<br />
<br />
For details on the internals of routing, see [[Routing implementation details]].<br />
&lt;noinclude&gt;[[Category:Tutorials]][[Category:Component Development]][[Category:Search Engine Friendly URLs]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Manifest_filesManifest files2014-08-29T12:25:28Z<p>Mvangeest: /* SQL */ Removed nonexistent attributes</p>
<hr />
<div>{{version|2.5,3.x}}<br />
<br />
Within Joomla there are manifest files for all of the extensions. These files include the general installation information as well as parameters for the configuration of the [[extension]] itself. Since Joomla! 2.5 {{JVer|2.5}}, there are very few differences between the manifest file formats for the different [[Extension types (technical definitions)|types of extensions]], allowing each type to access the full power of the Joomla! installer.<br />
<br />
==Naming conventions==<br />
The file must be named &lt;tt&gt;manifest.xml&lt;/tt&gt; or &lt;tt&gt;&lt;extension_name&gt;.xml&lt;/tt&gt; and located in the root directory of the installation package.<br />
<br />
==Syntax==<br />
<br />
=== Root element ===<br />
The primary tag of the installation file is: <br />
&lt;source lang=xml&gt;&lt;extension&gt;&lt;/extension&gt;&lt;/source&gt;<br />
<br />
This starting and closing tags are now valid for all extensions. The new tag &lt;code&gt;&lt;extension&gt;&lt;/code&gt; replaces the old &lt;code&gt;&lt;install&gt;&lt;/install&gt;&lt;/code&gt; from Joomla {{JVer|1.5}}. The following attributes are allowed within the tag:<br />
<br />
{|class=&quot;wikitable&quot;<br />
|-<br />
! style=&quot;width: 150px&quot; | Attribute || style=&quot;width: 150px&quot; | Values || Applicable&amp;nbsp;to || Description<br />
|-<br />
| type || &lt;code&gt;component&lt;/code&gt;&lt;br /&gt;&lt;code&gt;file&lt;/code&gt;&lt;br /&gt;&lt;code&gt;language&lt;/code&gt;&lt;br /&gt;&lt;code&gt;library&lt;/code&gt;&lt;br /&gt;&lt;code&gt;module&lt;/code&gt;&lt;br /&gt;&lt;code&gt;package&lt;/code&gt;&lt;br /&gt;&lt;code&gt;plugin&lt;/code&gt;&lt;br /&gt;&lt;code&gt;template&lt;/code&gt; || All extensions<br />
| This attribute describes the type of the extension for the installer. Based on this type further requirements to sub-tags apply.<br />
|-<br />
| version<br />
| &lt;code&gt;2.5&lt;/code&gt;&lt;br /&gt;&lt;code&gt;3.0&lt;/code&gt; || All extensions<br />
| String that identifies the version of Joomla for which this extension is developed.<br />
|-<br />
| method<br />
| &lt;code&gt;install&lt;/code&gt;&lt;br /&gt;&lt;code&gt;upgrade&lt;/code&gt; || All extensions<br />
| The default value &lt;code&gt;install&lt;/code&gt; will be also used if the method attribute is not used. The &lt;code&gt;install&lt;/code&gt; value means the installer will gracefully stop if it finds any existing file/folder of the new extension.<br />
|-<br />
| client<br />
| &lt;code&gt;site&lt;/code&gt;&lt;br /&gt;&lt;code&gt;administrator&lt;/code&gt; || Modules<br />
| The client attribute allows you to specify for which application client the new module is available.<br />
|-<br />
| group<br />
| ''string'' || Plugins<br />
| The group name specifies for which group of plugins the new plugin is available. The existing groups are the folder names within the directory &lt;tt&gt;/plugins&lt;/tt&gt;. The installer will create new folder names for group names that do not exist yet.<br />
|}<br />
<br />
<br />
=== Metadata ===<br />
<br />
The following elements can be used to insert metadata. None of these elements are required; if they are present, they must be a child of the root element.<br />
<br />
&lt;pre&gt;<br />
&lt;name&gt; &amp;ndash; raw component name (e.g. com_banners). <br />
&lt;author&gt; &amp;ndash; author's name (e.g. Joomla! Project)<br />
&lt;creationDate&gt; &amp;ndash; date of creation or release (e.g. April 2006)<br />
&lt;copyright&gt; &amp;ndash; a copyright statement (e.g. (C) 2005 - 2011 Open Source Matters. All rights reserved.)<br />
&lt;license&gt; &amp;ndash; a license statement (e.g. NU General Public License version 2 or later; see LICENSE.txt)<br />
&lt;authorEmail&gt; &amp;ndash; author's email address (e.g. admin@joomla.org)<br />
&lt;authorUrl&gt; &amp;ndash; URL to the author's website (e.g. www.joomla.org)<br />
&lt;version&gt; &amp;ndash; the version number of the extension (e.g. 1.6.0)<br />
&lt;description&gt; &amp;ndash; the description of the component. This is a translatable field. (e.g. COM_BANNERS_XML_DESCRIPTION)<br />
&lt;/pre&gt;<br />
<br />
Note: The &lt;name&gt; and &lt;description&gt; tags are also translatable fields so that the name and description of the extension can be shown to the user in their native language.<br />
<br />
=== Front-end files ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files folder=&quot;from-folder&quot;&gt;<br />
&lt;filename&gt;example.php&lt;/filename&gt;<br />
&lt;folder&gt;examples&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;/source&gt;<br />
<br />
Files to copy to the front-end directory should be placed in the &lt;code&gt;&lt;files&gt;&lt;/code&gt; element. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from'''. Each file to copy must be represented by a &lt;code&gt;&lt;filename&gt;&lt;/code&gt; element. If you want to copy an entire folder at once, you can define it as a &lt;code&gt;&lt;folder&gt;&lt;/code&gt;.<br />
<br />
=== Media files ===<br />
<br />
&lt;source lang=&quot;xml&gt;<br />
&lt;media folder=&quot;media&quot; destination=&quot;com_example&quot;&gt;<br />
&lt;filename&gt;com_example_logo.png&lt;/filename&gt;<br />
&lt;folder&gt;css&lt;/folder&gt;<br />
&lt;folder&gt;js&lt;/folder&gt;<br />
&lt;/media&gt;<br />
&lt;/source&gt;<br />
<br />
This example will copy the file(s) (&lt;tt&gt;/media/com_example_logo.png&lt;/tt&gt;) and folders ( &lt;tt&gt;/media/css/&lt;/tt&gt; and &lt;tt&gt;/media/js/&lt;/tt&gt; ) listed to &lt;tt&gt;/media/com_example/&lt;/tt&gt;, creating the &lt;tt&gt;com_example&lt;/tt&gt; folder if required. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from''' (in this case, &lt;tt&gt;media&lt;/tt&gt;).<br />
<br />
Extensions should be storing assets they need to be web accessible (JS, CSS, images etc) in &lt;code&gt;media&lt;/code&gt;. Amongst other things this feature was added as step in the progression to multi-site support and the eventual move of code files (PHP) out of the web accessible areas of the server.<br />
<br />
Ref:<br />
* [https://groups.google.com/forum/#!msg/joomla-dev-cms/4CAASJqFY-k/PvPj14gP29EJ Google Groups - joomla-dev-cms thread]<br />
* [https://groups.google.com/forum/#!msg/joomla-dev-cms/uNmhX98sKbE/p8p68Jke680J Google Groups - joomla-dev-cms thread]<br />
<br />
=== Administration section ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;administration&gt;<br />
&lt;!-- various elements --&gt;<br />
&lt;/administration&gt;<br />
&lt;/source&gt;<br />
<br />
The administration section is defined in the &lt;code&gt;&lt;administration&gt;&lt;/code&gt; element. Since only [[Component|components]] apply to both the [[Site (Application)|site]] and the [[Administrator (Application)|administrator]], '''only component manifests can include this element'''.<br />
<br />
==== Back-end files ====<br />
<br />
Files to copy to the back-end directory should be placed in the &lt;code&gt;&lt;files&gt;&lt;/code&gt; element under the &lt;code&gt;&lt;administration&gt;&lt;/code&gt;. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from'''. See ''Front-end files'' for further rules.<br />
<br />
==== Menu links and submenus ====<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;menu&gt;COM_EXAMPLE&lt;/menu&gt;<br />
&lt;submenu&gt;<br />
&lt;menu link=&quot;anoption=avalue&quot;&gt;COM_EXAMPLE_SUBMENU_ANOPTION&lt;/menu&gt;<br />
&lt;menu view=&quot;viewname&quot;&gt;COM_EXAMPLE_SUBMENU_VIEWNAME&lt;/menu&gt;<br />
&lt;/submenu&gt;<br />
&lt;/source&gt;<br />
<br />
The text for the main menu item for the component is defined in the &lt;code&gt;&lt;menu&gt;&lt;/code&gt; item, a child of &lt;code&gt;&lt;administration&gt;&lt;/code&gt;. A &lt;code&gt;&lt;submenu&gt;&lt;/code&gt; element may also be present (also a child of &lt;code&gt;&lt;administration&gt;&lt;/code&gt;), which may contain more menu items defined by &lt;code&gt;&lt;menu&gt;&lt;/code&gt;.<br />
<br />
Additionally, each &lt;code&gt;&lt;menu&gt;&lt;/code&gt; item can define the following attributes:<br />
<br />
{| class=&quot;wikitable&quot;<br />
! style=&quot;width: 150px&quot; | Attribute || Description<br />
|-<br />
| link || A link to send the user to when the menu item is clicked<br />
|-<br />
| img || The (relative) path to an image (16x16 pixels) to appear beside the menu item. <br />
&lt;u&gt;Must be an url compatible as a file too (e.g. no spaces) !&lt;/u&gt;<br />
|-<br />
| alt ||<br />
|-<br />
| ''string'' || An URL parameter to add to the link. For example, &lt;code&gt;&lt;menu view=&quot;cpanel&quot;&gt;COM_EXAMPLE&lt;/menu&gt;&lt;/code&gt; in com_example's XML manifest would cause the URL of the menu item to be &lt;tt&gt;index.php?option=com_example&amp;view=cpanel&lt;/tt&gt;.<br />
|-<br />
|}<br />
<br />
The value inside the tag is the menu's label. Unlike Joomla! 1.5, you can not use a natural language string. For example, if you would enter &quot;Example Component&quot; instead of COM_EXAMPLE, it would result in your component name appearing as example-component in the menu and you would be unable to provide a translation. In order to provide a translation you need to create a file named en-GB.com_example.sys.ini in administrator/languages/en-GB (you can use the manifest's &lt;code&gt;&amp;lt;languages&amp;gt;&lt;/code&gt; tag to copy it during installation) or in administrator/components/com_example/language/en-GB. In the latter case, you must not include the translation file in the &lt;code&gt;&amp;lt;languages&amp;gt;&lt;/code&gt; tag. As long as you have placed the language directory in your &lt;code&gt;&lt;files&gt;&lt;/code&gt; tag, it will be copied along when the component is being installed.<br />
<br />
The contents of that file should be:<br />
&lt;source&gt;<br />
COM_EXAMPLE=&quot;Example Component&quot;<br />
COM_EXAMPLE_SUBMENU_ANOPTION=&quot;Another Option&quot;<br />
COM_EXAMPLE_SUBMENU_VIEWNAME=&quot;Another View&quot;<br />
<br />
&lt;/source&gt;<br />
<br />
Please note that the language string must be enclosed in double quotes, as per Joomla!'s translation standards. Important note: Joomla! 1.6 and later sorts the Component menu items based on the actual translation of the key you supply in your XML manifest. This means that the sorting order is correct no matter what you call your translation key and no matter which language the site is being displayed in. Essentially, Joomla! 1.6 fixed the wrong sorting of the Components menu experienced under Joomla! 1.5 for the majority (non-English speaking!) of Joomla! users.<br />
<br />
{{Needsinfo|In Platform 11.1 no alt attribute processed and if link provide in menu tag other provided attributes were ignore. The other tags are task, view, controller, act, layout, sub. Please confirm this, please.}}<br />
<br />
=== Configuration ===<br />
{{warning|Components '''do not support''' configuration definitions '''in the manifest'''. This is a way implemented in Joomla! 1.5. They can define configuration options for multiple levels using [[Component configuration metadata]].}}<br />
The &lt;code&gt;&lt;config&gt;&lt;/code&gt; element, a child of the root, describes the configuration options for the extension. If applicable, the options will be shown by the appropriate Manager (Plugin Manager, Module Manager or Template Manager). '''Configuration options can also be defined in a separate file named &lt;code&gt;config.xml&lt;/code&gt;. Its root element should be &lt;code&gt;&lt;config&gt;&lt;/code&gt;.'''<br />
<br />
{{:XML JForm form definitions}}<br />
<br />
=== SQL ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;install&gt;<br />
&lt;sql&gt;<br />
&lt;file driver=&quot;mysql&quot; charset=&quot;utf8&quot;&gt;sql/example.install.sql&lt;/file&gt;<br />
&lt;/sql&gt;<br />
&lt;/install&gt;<br />
&lt;uninstall&gt;<br />
&lt;sql&gt;<br />
&lt;file driver=&quot;mysql&quot; charset=&quot;utf8&quot;&gt;sql/example.uninstall.sql&lt;/file&gt;<br />
&lt;/sql&gt;<br />
&lt;/uninstall&gt;<br />
&lt;/source&gt;<br />
<br />
In the above example, we put the SQL files in the &lt;tt&gt;admin/sql&lt;/tt&gt; folder of the installation package. You have to include the &lt;tt&gt;sql&lt;/tt&gt; folder in the administration files (as described in ''Back-end files'').<br />
<br />
You can execute SQL during the installation and/or uninstallation using the &lt;code&gt;&lt;install&gt;&lt;/code&gt; and &lt;code&gt;&lt;uninstall&gt;&lt;/code&gt; elements, respectively. A &lt;code&gt;&lt;sql&gt;&lt;/code&gt; element should appear as a child of these elements. &lt;code&gt;&lt;sql&gt;&lt;/code&gt; can contain any number of &lt;code&gt;&lt;file&gt;&lt;/code&gt; elements, each defining a single SQL file to execute. Their database driver types are described by the &lt;code&gt;driver&lt;/code&gt; attribute, their character sets by the &lt;code&gt;charset&lt;/code&gt; attribute.<br />
<br />
==== Update of the SQL schema ====<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;update&gt;<br />
&lt;schemas&gt;<br />
&lt;schemapath type=&quot;mysql&quot;&gt;sql/updates/mysql&lt;/schemapath&gt;<br />
&lt;schemapath type=&quot;sqlsrv&quot;&gt;sql/updates/sqlsrv&lt;/schemapath&gt;<br />
&lt;/schemas&gt;<br />
&lt;/update&gt;<br />
&lt;/source&gt;<br />
<br />
Since 1.6, there is also an &lt;code&gt;&lt;update&gt;&lt;/code&gt; tag, which allows you to provide a series of SQL files to update the current schema.<br />
<br />
=== Language files ===<br />
In Joomla! 1.5, extension developers had to put extension language files in the Joomla! main language file, using the &lt;languages&gt;..&lt;/languages&gt; tag as shown below. '''This method can still be used in''' {{rarr|2.5,3.x}}.<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;!-- Joomla! 1.5 language tag --&gt;<br />
&lt;languages folder=&quot;langfiles&quot;&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;en-GB.com_example.ini&lt;/language&gt;<br />
&lt;/languages&gt;<br />
&lt;/source&gt;<br />
<br />
Since Joomla! 1.6 it has been encouraged placing your extension's language files in your extension folder. Joomla! will then automatically load your extension's language files.<br />
<br />
By storing extension language files in the extension folder, you gain the benefit of isolating and protecting your extension's language files. For example, an administrator removes a language from their Joomla! installation. Your extension's language files will not be removed. They will remain in place and will be available if the language is installed again.<br />
<br />
The structure of the language folder for frontend and backend is the same. You put them in the language tag (e.g. '''en-GB''' ) of each language in your language folder i.e. '''language/en-GB/'''. You have to specify those folders in the front-end and back-end files too.<br />
<br />
In your manifest you simply include the ''''language'''' folder in your files section, the sub-directories for each language automatically be copied. Inside the &lt;files&gt; group you simply add a &lt;folder&gt; element alongside the items in the '''&lt;files&gt;''' group as shown in this example:<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files&gt;<br />
&lt;filename plugin=&quot;alpha&quot;&gt;alpha.php&lt;/filename&gt;<br />
&lt;folder&gt;sql&lt;/folder&gt;<br />
&lt;folder&gt;language&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;/source&gt;<br />
<br />
It is also notable that both ways can work together. Here is an example from core:<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files&gt;<br />
&lt;filename plugin=&quot;languagecode&quot;&gt;languagecode.php&lt;/filename&gt;<br />
&lt;filename&gt;index.html&lt;/filename&gt;<br />
&lt;folder&gt;language&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;languages&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;language/en-GB/en-GB.plg_system_languagecode.ini&lt;/language&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;language/en-GB/en-GB.plg_system_languagecode.sys.ini&lt;/language&gt;<br />
&lt;/languages&gt;<br />
&lt;/source&gt;<br />
<br />
The advantages of this solution are the following:<br />
<br />
All ini files present in the core folder have precedence over the files in the extension language/ folder.<br />
For example a sys.ini file will always be loaded from core folders in back-end if it exists, except when installing an extension which contains a sys.ini file in a language folder. In that case and only that case, the sys.ini file in the extension folder will display its translated content at install time. This is very handy as a developer can have 2 sys.ini files with different contents. A description of the successful install as well as a tutorial in back-end for example.<br />
<br />
Also, it is much easier for a user needing an ini file for an extension that does not provide it in the language desired, to add it in the main folders. No risk for it to be deleted in case of uninstalling the extension by mistake or any other reason.<br />
<br />
See also:<br />
*[[J2.5:Making non-core language packs|Making non-core language packs]]<br />
*[[Creating language packs for extensions in Joomla 2.5]]<br />
<br />
During development you can turn on language debugging in the Joomla! global configuration. So you can investigate if a problems arises. As of 3.2, this is necessary to help debug as en-GB is '''always''' loaded first when not in debug mode to prevent displaying Constants.<br />
<br />
=== Script file ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;scriptfile&gt;example.script.php&lt;/scriptfile&gt;<br />
&lt;/source&gt;<br />
<br />
An optional '''script file''' (PHP code that is run before, during and/or after installation, uninstallation and upgrading) can be defined using a &lt;code&gt;&lt;scriptfile&gt;&lt;/code&gt; element. This file should contain a class named &quot;&lt;element_name&gt;IntallerScript&quot; where &lt;element_name&gt; is the name of your extension (e.g. com_componentname, mod_modulename, etc.). Plugins requires to state the group (e.g. plgsystempluginname). Library packages do not support scriptfiles. The structure of the class is as follows:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
class com_componentnameInstallerScript<br />
{<br />
/**<br />
* Constructor<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*/<br />
public function __construct(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called before any type of action<br />
*<br />
* @param string $route Which action is happening (install|uninstall|discover_install|update)<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function preflight($route, JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called after any type of action<br />
*<br />
* @param string $route Which action is happening (install|uninstall|discover_install|update)<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function postflight($route, JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on installation<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function install(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on update<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function update(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on uninstallation<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*/<br />
public function uninstall(JAdapterInstance $adapter);<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
=== Update servers ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;updateservers&gt;<br />
&lt;server type=&quot;extension&quot; priority=&quot;1&quot; name=&quot;Extension Update Site&quot;&gt;http://example.com/extension.xml&lt;/server&gt;<br />
&lt;server type=&quot;collection&quot; priority=&quot;2&quot; name=&quot;Collection Update Site&quot;&gt;http://example.com/collection.xml&lt;/server&gt;<br />
&lt;/updateservers&gt;<br />
&lt;/source&gt;<br />
<br />
Update servers can be defined in the &lt;code&gt;&lt;updateservers&gt;&lt;/code&gt; element, a child of the root. This element may contain one or more &lt;code&gt;&lt;server&gt;&lt;/code&gt; element, each describing a location to fetch updates from. Each &lt;code&gt;&lt;server&gt;&lt;/code&gt; item can define the following attributes:<br />
<br />
{| class=&quot;wikitable&quot;<br />
! style=&quot;width: 150px&quot; | Attribute || style=&quot;width: 150px&quot; | Values || Description<br />
|-<br />
| type || &lt;code&gt;extension&lt;/code&gt;&lt;br /&gt;&lt;code&gt;collection&lt;/code&gt; || The update server type<br />
|-<br />
| priority || ''integer'' || The priority of the update server<br />
|-<br />
| name || ''string'' || The name of the update server<br />
|}<br />
<br />
More info:<br />
* [[J2.5:Developing a MVC Component/Adding an update server|Building a Joomla! Extension - Adding an update server]]<br />
* [[J2.5:Managing Component Updates|Managing Component Updates in Joomla 2.5]]<br />
<br />
== Examples ==<br />
For a real-life example, see [https://github.com/joomla/joomla-cms/blob/2.5.x/administrator/components/com_banners/banners.xml the manifest of the Banner component in the latest version of Joomla! 2.5].<br />
<br />
The Joomla testing process uses several extensions to test whether the installer works correctly. The latest versions of the manifests of these extensions are:<br />
<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/com_alpha/alpha.xml com_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/mod_alpha/mod_alpha.xml mod_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/plg_system_alpha/alpha.xml plg_system_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/tpl_simple/templateDetails.xml tpl_simple manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/lng_xx-XX/xx-XX.xml lng_xx-XX manifest]<br />
<br />
== Contributors ==<br />
*[[User:akede|Alex Kempkens]]<br />
*[[User:dperaza|Daniel Peraza]]<br />
*[[User:nikosdion|Nicholas K. Dionysopoulos]]<br />
*[[User:mrs.siam|Prasit Gebsaap]]<br />
*[[User:cppl|Craig Phillips]]<br />
<br />
<br />
[[Category:Extension development]]<br />
[[Category:Specifications]]</div>Mvangeest//docs.joomla.org/Supporting_SEF_URLs_in_your_componentSupporting SEF URLs in your component2014-08-28T22:22:01Z<p>Mvangeest: /* Preparing Your Data for Routing */</p>
<hr />
<div>{{version/tutor|2.5,3.1}}<br />
{{:Search Engine Friendly URLs}}<br />
In Joomla!, each [[component]] is responsible for handling its own SEF URLs. Therefore, as the [[Developers|developer]] of a component, you will have to create your own '''router''' to allow your component to use SEF URLs.<br />
<br />
== The Concept ==<br />
<br />
Assuming you are following standard development practices, your component is probably using &quot;system URLs&quot; that look a lot like &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;, and your goal is to transform this into &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;. As the developer, you have two tasks: signalling the system that certain pieces of text are URLs and need to be transformed, and explaining the system how to transform URLs.<br />
<br />
=== Applying &lt;code&gt;JRoute::_&lt;/code&gt; ===<br />
<br />
It is difficult and inefficient for Joomla! to figure out which parts of your component's output are URLs. To support SEF URLs, you will need to change URL-generating code so that it applies &lt;code&gt;JRoute::_&lt;/code&gt; before outputting the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
echo JRoute::_('index.php?view=article&amp;id=1&amp;catid=20');<br />
&lt;/source&gt;<br />
<br />
Notice that it is possible to leave out the parameters &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;Itemid&lt;/code&gt;. &lt;code&gt;option&lt;/code&gt; defaults to the name of the component currently being executed, and &lt;code&gt;Itemid&lt;/code&gt; defaults to the current menu item's ID.<br />
<br />
In general, you should only apply this to URLs that users and/or search engines are able to see. For example, there is no need to transform URLs used in redirects that immediately result in other redirects.<br />
<br />
If the user turns off SEF URLs in the site's settings, &lt;code&gt;JRoute::_&lt;/code&gt; will produce working non-SEF URLs without any changes to the code.<br />
<br />
=== Writing a router ===<br />
<br />
You'll also need to write a router, which is a single file with two functions that convert system URLs to and from SEF URLs. This file needs to be placed at &lt;tt&gt;/components/com_yourcomponent/router.php&lt;/tt&gt;.<br />
<br />
The first function, &lt;code&gt;[componentname]BuildRoute(&amp;$query)&lt;/code&gt;, must transform an array of URL parameters into an array of segments that will form the SEF URL. Schematically, the transformation works as follows:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; &lt;code&gt;JRoute::_&lt;/code&gt;, called by your component or any other extension<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentBuildRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal route building (for display)<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
The second function, &lt;code&gt;[componentname]ParseRoute($segments)&lt;/code&gt;, must transform an array of segments back into an array of URL parameters. Schematically:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal route parsing<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentParseRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
The two functions must cooperate in such a way that the original URL can be reconstructed. You can think of &lt;code&gt;BuildRoute&lt;/code&gt; as a form of [[wikipedia:Encoding|encoding]] and &lt;code&gt;ParseRoute&lt;/code&gt; as the corresponding decoding. When the original URL isn't properly reproduced, your component will stop working.<br />
<br />
== Preparing Your Data for Routing ==<br />
<br />
Clearly, any URL format needs to contain some kind of information that identifies the data you want to show. If your system URLs look like &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;, that information is currently the &lt;tt&gt;id&lt;/tt&gt; URL parameter (&lt;tt&gt;id=1&lt;/tt&gt;). You probably want your SEF URLs to contain a textual description of the data they point to. In Joomla!, this is usually done by giving your users a way to enter an '''alias''' to be used in the URL.<br />
<br />
=== The Alias ===<br />
<br />
Even if your users can enter an alias, they might not do so, leaving the generation of a sensible alias up to your component. If your data has a title field, you can use that as a candidate for the alias (like the core [[Content]] component does).<br />
<br />
Considering that the alias will be used in URLs, it has to be URL safe. Joomla! provides a method making arbitrary strings URI safe, which includes replacing accented UTF­8 characters by their ASCII­7 equivalents, white spaces by hyphens, etc. Whether the user entered the alias or a candidate has been chosen automatically, you should ensure that the above requirements for a URL safe alias are met. A good place for implementing this, if you are using &lt;code&gt;JTable&lt;/code&gt;, is the &lt;code&gt;JTable::check()&lt;/code&gt; method, which is called during the save process. Have a look at this example code:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function check()<br />
{<br />
jimport('joomla.filter.output');<br />
if (empty($this-&gt;alias))<br />
{<br />
$this-&gt;alias = $this-&gt;title;<br />
}<br />
$this-&gt;alias = JFilterOutput::stringURLSafe($this-&gt;alias);<br />
<br />
/* All your other checks */<br />
return true;<br />
}<br />
&lt;/source&gt;<br />
<br />
If the alias field is empty the title is used as alias. Then the alias is made URL safe using the &lt;code&gt;JFilterOutput::stringURLSafe()&lt;/code&gt; method.<br />
<br />
=== The Slug ===<br />
<br />
A '''slug''' is used to minimise the amount of code you need to support SEF URLs. It consists of the numerical identifier (&lt;tt&gt;id&lt;/tt&gt;) your system URLs used, a colon (&lt;tt&gt;:&lt;/tt&gt;), and the alias you created as described above. <br />
<br />
Consider a SEF URL for an [[Article]] with &lt;tt&gt;id&lt;/tt&gt; 1 and title &quot;Welcome to Joomla!&quot;. The automatically generated alias for this article is &lt;tt&gt;welcome-to-joomla&lt;/tt&gt;, and the slug becomes &lt;tt&gt;1­:welcome­-to­-joomla&lt;/tt&gt;. In the [[Content]] component, the two elements are combined during the database query in the model (&lt;code&gt;a&lt;/code&gt; represents &lt;code&gt;#__content&lt;/code&gt;):<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$query = 'SELECT a.*, '.<br />
'CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(&quot;:&quot;, a.id, a.alias) ELSE a.id END as slug,'<br />
/*...*/;&lt;/source&gt;<br />
<br />
The advantage of this method of creating a slug is that you can simply use the slug as a drop-in replacement for the id in most places. For example, you don't need to check for and remove the colon and the alias from the request data manually: if you use [[Retrieving request data using JInput|JInput]]'s &lt;code&gt;int&lt;/code&gt; (integer) filter, it will do that automatically.<br />
<br />
== Routing URLs ==<br />
<br />
The &lt;code&gt;JRoute::_&lt;/code&gt; method translates the internal Joomla! URL to a custom URL. &lt;code&gt;JRoute::_&lt;/code&gt; has three parameters and its prototype is:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_($url, $xhtml = true, $ssl = null);&lt;/source&gt;<br />
<br />
Where:<br />
<br />
* &lt;code&gt;$url&lt;/code&gt; is a string containing the absolute or relative internal Joomla! URL.<br />
* &lt;code&gt;$xhtml&lt;/code&gt; is a boolean value that specifies whether or not the output should be in XHTML. This parameter is optional and if omitted defaults to true.<br />
* &lt;code&gt;$ssl&lt;/code&gt; is an integer value that specifies whether the URI should be secure. It should be set to 1 to force the URI to be secure using the global secure site URI, 0 to leave it in the same state as when it was passed, and -1 to force the URI to be unsecure using the global unsecure site URI.<br />
<br />
The most important parameter is &lt;code&gt;$url&lt;/code&gt;. A call to this method might look like:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_('index.php?view=article&amp;id=' . $row-&gt;slug);&lt;/source&gt;<br />
<br />
&lt;code&gt;$row-­&gt;slug&lt;/code&gt; is the value that was generated in step 2 from a combination of id and title alias.<br />
<br />
Another advantage of using &lt;code&gt;JRoute::_&lt;/code&gt; is that the router now handles &lt;code&gt;$option&lt;/code&gt; (the component name) and the &lt;code&gt;$Itemid&lt;/code&gt; (the menu item ID). The component itself doesn't have to know its name (&lt;code&gt;$option&lt;/code&gt;) or the active menu item (&lt;code&gt;$Itemid&lt;/code&gt;) like it did in previous version of Joomla!.<br />
<br />
It is important that you think about the sequence of the URL parameter in this stage. This will be more clear when we have a deeper look at the &lt;tt&gt;router.php&lt;/tt&gt; in the next section.<br />
<br />
The building process of JRouter is divided into two steps:<br />
<br />
* Create the application route. The application route is fully handled by JRouter and the component developer doesn’t have to do anything to make it work.<br />
* Create the component route. To create the component route, JRouter looks for the &lt;tt&gt;router.php&lt;/tt&gt; in the component directory which is responsible for building the route for the component.<br />
<br />
== The Component Router ==<br />
<br />
We will have two functions in the &lt;tt&gt;router.php&lt;/tt&gt;. One is responsible for building the URL and the other is responsible for parsing it. In the next examples, a very basic and a more advanced one, we assume that we have three views that links can point to. The first is a categories overview (&lt;code&gt;view=categories&lt;/code&gt;), the second is a single category (&lt;code&gt;view=category&lt;/code&gt;) and the third is a single article (&lt;code&gt;view=article&lt;/code&gt;).<br />
<br />
The file &lt;tt&gt;router.php&lt;/tt&gt; should be in the site area of your component. It is not used on admin/backend pages. Don't forget to add it to your XML [[Manifest files|manifest file]] in the site folder.<br />
<br />
=== A Simple Example ===<br />
<br />
This simple example will illustrate the basics of implementing a router for your component.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if (isset($query['view']))<br />
{<br />
$segments[] = $query['view'];<br />
unset($query['view']);<br />
}<br />
if (isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset($query['id']);<br />
};<br />
return $segments;<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
&lt;code&gt;JRouter&lt;/code&gt; passes a &lt;code&gt;$query&lt;/code&gt; array to the &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; function. This function will add the relevant parts of the array to the $segments array in the right order and will return the properly ordered array. The content of the &lt;code&gt;$query&lt;/code&gt; array needs to be unset, otherwise &lt;code&gt;JRouter&lt;/code&gt; will add it to the URL in the form of a query string (i.e. any variables that are not handled by the router will be passed in the query string).<br />
<br />
The prefix ''componentname'' is the name for your component, as found in the directory holding the component's files. For instance, a component &quot;Magic&quot; in directory &lt;tt&gt;/components/com_magic/...&lt;/tt&gt; would use a prefix &lt;code&gt;magic&lt;/code&gt; (all lower case).<br />
<br />
The next function in the &lt;tt&gt;router.php&lt;/tt&gt; parses the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute($segments)<br />
{<br />
$vars = array();<br />
switch($segments[0])<br />
{<br />
case 'categories':<br />
$vars['view'] = 'categories';<br />
break;<br />
case 'category':<br />
$vars['view'] = 'category';<br />
$id = explode(':', $segments[1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'article':<br />
$vars['view'] = 'article';<br />
$id = explode(':', $segments[1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
What happens here? In the function &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; we arranged the items in the &lt;code&gt;$query&lt;/code&gt; array in a specific sequence. This means that in this example the view is first and the id is second in the array.<br />
<br />
By reading &lt;code&gt;$segments[0]&lt;/code&gt;, we access the name of the view. We set the right view and/or identifier depending on its value and we return the &lt;code&gt;$vars&lt;/code&gt; array to &lt;code&gt;JRouter&lt;/code&gt;. &lt;code&gt;$vars&lt;/code&gt; should be an associative array similar to the array that was passed to the BuildRoute method.<br />
<br />
The above example of the &lt;tt&gt;router.php&lt;/tt&gt; is a very simple way to generate SEF URLs but should show how this works quite clearly.<br />
<br />
The generated URL in this example contains the name of the view and doesn't reflect the content hierarchy:<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[view]/[slug]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
=== A More Advanced Example ===<br />
<br />
In the next example we will try to get rid of the need for the view and we will try to reflect the current hierarchy level in the URL.<br />
<br />
The goal is URL's that look like:<br />
<br />
* When viewing an article: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]/[article]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing a category: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing the categories overview: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
Let's assume we have done step 1 and 2 also for the category.<br />
<br />
The link to the article would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_('index.php?view=article&amp;catid=' . $row-­&gt;catslug . '&amp;id='.$row-­&gt;slug);<br />
&lt;/source&gt;<br />
<br />
And the Link to the category would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_('index.php?view=category&amp;id=' . $row-&gt;catslug);<br />
&lt;/source&gt;<br />
<br />
The corresponding &lt;tt&gt;router.php&lt;/tt&gt;:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function [componentname]BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if (isset($query['catid']))<br />
{<br />
$segments[] = $query['catid'];<br />
unset($query['catid']);<br />
};<br />
if (isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset($query['id']);<br />
};<br />
unset($query['view']);<br />
return $segments;<br />
}<br />
&lt;/source&gt;<br />
<br />
The difference now is that we don’t add the name of the view to the &lt;code&gt;$segments&lt;/code&gt; array. We still unset the view key since otherwise, &lt;code&gt;JRouter&lt;/code&gt; would add it to the URL as part of the query string. Another new thing here is the additional parameter catid that we push into the &lt;code&gt;$segments&lt;/code&gt; array.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute($segments)<br />
{<br />
$vars = array();<br />
$app = JFactory::getApplication();<br />
$menu = $app-&gt;getMenu();<br />
$item = $menu-&gt;getActive();<br />
// Count segments<br />
$count = count($segments);<br />
// Handle View and Identifier<br />
switch ($item-&gt;query['view'])<br />
{<br />
case 'categories':<br />
if ($count == 1)<br />
{<br />
$vars['view'] = 'category';<br />
}<br />
if ($count == 2)<br />
{<br />
$vars['view'] = 'article';<br />
}<br />
$id = explode(':', $segments[$count-1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'category':<br />
$id = explode(':', $segments[$count-1]);<br />
$vars['id'] = (int) $id[0];<br />
$vars['view'] = 'article';<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
You can see that this ParseRoute function has a lot of different code parts in comparison to the previous. The reason for this is simple. We don’t have the name of the view in the &lt;code&gt;$segments&lt;/code&gt; array and we need to find another way to determine it.<br />
<br />
We need to find out which level of hierarchy we are in by receiving the root element. We do this by looking to the view name of the active menu item:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$item-­&gt;query['view']<br />
&lt;/source&gt;<br />
<br />
Also we need to know the number of items in the &lt;code&gt;$segments&lt;/code&gt; array:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$count = count($segments);<br />
&lt;/source&gt;<br />
<br />
With this information we can correctly set the view for all possible three cases:<br />
<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has two items (&lt;code&gt;$catid&lt;/code&gt; and &lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to an article.<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has one item (&lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to a category.<br />
* The menu item is a link to a category. In this case, we know that any item in the &lt;code&gt;$segments&lt;/code&gt; array is the identifier for an article.<br />
<br />
The result of all this code is clean and human-readable component URLs.<br />
<br />
== Routers and Menu Items ==<br />
<br />
A last important part of creating a router is considering what to do with menu items. As explained on [[Search Engine Friendly URLs]], the output of the component router is used ''after'' the first segment of a route, the first segment being the menu item's alias. This creates a difficult question: how is your router and/or other code to know which menu item to route through?<br />
<br />
Suppose, for example, that your component is currently producing output for the page &lt;tt&gt;/dogs&lt;/tt&gt;, which lists all dogs in the system. Of course, the items in the list need to be links to pages that display more details about one dog. What should the URL to the dog with ID 21 and name Fido become? Using a router that works according to the principles we've seen so far, the route that is produced is &lt;tt&gt;dogs/21-fido&lt;/tt&gt;, or with some additional work &lt;tt&gt;/dogs/fido&lt;/tt&gt;. But perhaps the user has created a menu item with the alias &lt;tt&gt;mydoggy&lt;/tt&gt; which displays exactly that dog's details. Then it is probably the user's intention to route this URL through that menu item, and the item in the list should link to the page &lt;tt&gt;/mydoggy&lt;/tt&gt;.<br />
<br />
More generally, whenever you are building a route, you will need to find the menu item that is most suitable as a ''starting point'' for building your route. The term ''starting point'' is emphasized because the rest of the route depends on the configuration of the menu item. In our example above, &lt;tt&gt;/dogs/21-fido&lt;/tt&gt; is an acceptable route, &lt;tt&gt;/mydoggy&lt;/tt&gt; is arguably even better, but &lt;tt&gt;/mydoggy/21-fido&lt;/tt&gt; is simply wrong, since &lt;tt&gt;/mydoggy&lt;/tt&gt; is in itself a menu item that is set up to display &lt;tt&gt;fido&lt;/tt&gt;'s information.<br />
<br />
Several approaches are available to tackle this problem. Joomla!'s core components take a mixed approach, separating responsibilities in two units of code: the router itself and the so-called &lt;code&gt;[componentname]RouteHelper&lt;/code&gt;. The &lt;code&gt;[componentname]RouteHelper&lt;/code&gt; provides methods that find the most suitable menu item for a given piece of data to be displayed, while the router analyzes the menu item and puts any information that is not determined by the menu item's configuration into the route. This does mean that the ''calling code'' must explicitly call the helper's method before routing (&lt;code&gt;echo JRoute::_(DogsRouteHelper::getDogRoute(21));&lt;/code&gt;).<br />
<br />
== See Also ==<br />
<br />
There is a useful thread on this subject here: [[jtopic:148632]] (note, may be out of date)<br />
<br />
For details on the internals of routing, see [[Routing implementation details]].<br />
&lt;noinclude&gt;[[Category:Tutorials]][[Category:Component Development]][[Category:Search Engine Friendly URLs]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Supporting_SEF_URLs_in_your_componentSupporting SEF URLs in your component2014-08-28T00:13:17Z<p>Mvangeest: /* Preparing Your Data for Routing */</p>
<hr />
<div>{{version/tutor|2.5,3.1}}<br />
{{:Search Engine Friendly URLs}}<br />
In Joomla!, each [[component]] is responsible for handling its own SEF URLs. Therefore, as the [[Developers|developer]] of a component, you will have to create your own '''router''' to allow your component to use SEF URLs.<br />
<br />
== The Concept ==<br />
<br />
Assuming you are following standard development practices, your component is probably using &quot;system URLs&quot; that look a lot like &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;, and your goal is to transform this into &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;. As the developer, you have two tasks: signalling the system that certain pieces of text are URLs and need to be transformed, and explaining the system how to transform URLs.<br />
<br />
=== Applying &lt;code&gt;JRoute::_&lt;/code&gt; ===<br />
<br />
It is difficult and inefficient for Joomla! to figure out which parts of your component's output are URLs. To support SEF URLs, you will need to change URL-generating code so that it applies &lt;code&gt;JRoute::_&lt;/code&gt; before outputting the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
echo JRoute::_('index.php?view=article&amp;id=1&amp;catid=20');<br />
&lt;/source&gt;<br />
<br />
Notice that it is possible to leave out the parameters &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;Itemid&lt;/code&gt;. &lt;code&gt;option&lt;/code&gt; defaults to the name of the component currently being executed, and &lt;code&gt;Itemid&lt;/code&gt; defaults to the current menu item's ID.<br />
<br />
In general, you should only apply this to URLs that users and/or search engines are able to see. For example, there is no need to transform URLs used in redirects that immediately result in other redirects.<br />
<br />
If the user turns off SEF URLs in the site's settings, &lt;code&gt;JRoute::_&lt;/code&gt; will produce working non-SEF URLs without any changes to the code.<br />
<br />
=== Writing a router ===<br />
<br />
You'll also need to write a router, which is a single file with two functions that convert system URLs to and from SEF URLs. This file needs to be placed at &lt;tt&gt;/components/com_yourcomponent/router.php&lt;/tt&gt;.<br />
<br />
The first function, &lt;code&gt;[componentname]BuildRoute(&amp;$query)&lt;/code&gt;, must transform an array of URL parameters into an array of segments that will form the SEF URL. Schematically, the transformation works as follows:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; &lt;code&gt;JRoute::_&lt;/code&gt;, called by your component or any other extension<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentBuildRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal route building (for display)<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
The second function, &lt;code&gt;[componentname]ParseRoute($segments)&lt;/code&gt;, must transform an array of segments back into an array of URL parameters. Schematically:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal route parsing<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentParseRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
The two functions must cooperate in such a way that the original URL can be reconstructed. You can think of &lt;code&gt;BuildRoute&lt;/code&gt; as a form of [[wikipedia:Encoding|encoding]] and &lt;code&gt;ParseRoute&lt;/code&gt; as the corresponding decoding. When the original URL isn't properly reproduced, your component will stop working.<br />
<br />
== Preparing Your Data for Routing ==<br />
<br />
Clearly, any URL format needs to contain some kind of information that identifies the data you want to show. If your system URLs look like &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;, that information is currently the &lt;tt&gt;id&lt;/tt&gt; URL parameter (&lt;tt&gt;id=1&lt;/tt&gt;). You probably want your SEF URLs to contain a textual description of the data they point to. In Joomla!, this is usually done by giving your users a way to enter an '''alias''' to be used in the URL.<br />
<br />
=== The Alias ===<br />
<br />
Even if your users can enter an alias, they might not do so, leaving the generation of a sensible alias up to your component. If your data has a title field, you can use that as a candidate alias (like the core [[Content]] component does).<br />
<br />
Considering that the alias will be used in URLs, it has to be URL safe. Joomla! provides a method making arbitrary strings URI safe, which includes replacing accented UTF­8 characters by their ASCII­7 equivalents, white spaces by hyphens, etc. Whether the user entered the alias or a candidate has been chosen automatically, you should ensure that the above requirements for a URL safe alias are met. A good place for implementing this, if you are using &lt;code&gt;JTable&lt;/code&gt;, is the &lt;code&gt;JTable::check()&lt;/code&gt; method, which is called during the save process. Have a look at this example code:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function check()<br />
{<br />
jimport('joomla.filter.output');<br />
if (empty($this-&gt;alias))<br />
{<br />
$this-&gt;alias = $this-&gt;title;<br />
}<br />
$this-&gt;alias = JFilterOutput::stringURLSafe($this-&gt;alias);<br />
<br />
/* All your other checks */<br />
return true;<br />
}<br />
&lt;/source&gt;<br />
<br />
If the alias field is empty the title is used as alias. Then the alias is made URL safe using the &lt;code&gt;JFilterOutput::stringURLSafe()&lt;/code&gt; method.<br />
<br />
=== The Slug ===<br />
<br />
A '''slug''' is used to minimise the amount of code you need to support SEF URLs. It consists of the numerical identifier (&lt;tt&gt;id&lt;/tt&gt;) your system URLs used, a colon (&lt;tt&gt;:&lt;/tt&gt;), and the alias you created as described above. <br />
<br />
Consider a SEF URL for an [[Article]] with &lt;tt&gt;id&lt;/tt&gt; 1 and title &quot;Welcome to Joomla!&quot;. The automatically generated alias for this article is &lt;tt&gt;welcome-to-joomla&lt;/tt&gt;, and the slug becomes &lt;tt&gt;1­:welcome­-to­-joomla&lt;/tt&gt;. In the [[Content]] component, the two elements are combined during the database query in the model (&lt;code&gt;a&lt;/code&gt; represents &lt;code&gt;#__content&lt;/code&gt;):<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$query = 'SELECT a.*, '.<br />
'CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(&quot;:&quot;, a.id, a.alias) ELSE a.id END as slug,'<br />
/*...*/;&lt;/source&gt;<br />
<br />
The advantage of this method of creating a slug is that you can simply use the slug as a drop-in replacement for the id in most places. For example, you don't need to check for and remove the colon and the alias from the request data manually: if you use [[Retrieving request data using JInput|JInput]]'s &lt;code&gt;int&lt;/code&gt; (integer) filter, it will do that automatically.<br />
<br />
== Routing URLs ==<br />
<br />
The &lt;code&gt;JRoute::_&lt;/code&gt; method translates the internal Joomla! URL to a custom URL. &lt;code&gt;JRoute::_&lt;/code&gt; has three parameters and its prototype is:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_($url, $xhtml = true, $ssl = null);&lt;/source&gt;<br />
<br />
Where:<br />
<br />
* &lt;code&gt;$url&lt;/code&gt; is a string containing the absolute or relative internal Joomla! URL.<br />
* &lt;code&gt;$xhtml&lt;/code&gt; is a boolean value that specifies whether or not the output should be in XHTML. This parameter is optional and if omitted defaults to true.<br />
* &lt;code&gt;$ssl&lt;/code&gt; is an integer value that specifies whether the URI should be secure. It should be set to 1 to force the URI to be secure using the global secure site URI, 0 to leave it in the same state as when it was passed, and -1 to force the URI to be unsecure using the global unsecure site URI.<br />
<br />
The most important parameter is &lt;code&gt;$url&lt;/code&gt;. A call to this method might look like:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_('index.php?view=article&amp;id=' . $row-&gt;slug);&lt;/source&gt;<br />
<br />
&lt;code&gt;$row-­&gt;slug&lt;/code&gt; is the value that was generated in step 2 from a combination of id and title alias.<br />
<br />
Another advantage of using &lt;code&gt;JRoute::_&lt;/code&gt; is that the router now handles &lt;code&gt;$option&lt;/code&gt; (the component name) and the &lt;code&gt;$Itemid&lt;/code&gt; (the menu item ID). The component itself doesn't have to know its name (&lt;code&gt;$option&lt;/code&gt;) or the active menu item (&lt;code&gt;$Itemid&lt;/code&gt;) like it did in previous version of Joomla!.<br />
<br />
It is important that you think about the sequence of the URL parameter in this stage. This will be more clear when we have a deeper look at the &lt;tt&gt;router.php&lt;/tt&gt; in the next section.<br />
<br />
The building process of JRouter is divided into two steps:<br />
<br />
* Create the application route. The application route is fully handled by JRouter and the component developer doesn’t have to do anything to make it work.<br />
* Create the component route. To create the component route, JRouter looks for the &lt;tt&gt;router.php&lt;/tt&gt; in the component directory which is responsible for building the route for the component.<br />
<br />
== The Component Router ==<br />
<br />
We will have two functions in the &lt;tt&gt;router.php&lt;/tt&gt;. One is responsible for building the URL and the other is responsible for parsing it. In the next examples, a very basic and a more advanced one, we assume that we have three views that links can point to. The first is a categories overview (&lt;code&gt;view=categories&lt;/code&gt;), the second is a single category (&lt;code&gt;view=category&lt;/code&gt;) and the third is a single article (&lt;code&gt;view=article&lt;/code&gt;).<br />
<br />
The file &lt;tt&gt;router.php&lt;/tt&gt; should be in the site area of your component. It is not used on admin/backend pages. Don't forget to add it to your XML [[Manifest files|manifest file]] in the site folder.<br />
<br />
=== A Simple Example ===<br />
<br />
This simple example will illustrate the basics of implementing a router for your component.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if (isset($query['view']))<br />
{<br />
$segments[] = $query['view'];<br />
unset($query['view']);<br />
}<br />
if (isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset($query['id']);<br />
};<br />
return $segments;<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
&lt;code&gt;JRouter&lt;/code&gt; passes a &lt;code&gt;$query&lt;/code&gt; array to the &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; function. This function will add the relevant parts of the array to the $segments array in the right order and will return the properly ordered array. The content of the &lt;code&gt;$query&lt;/code&gt; array needs to be unset, otherwise &lt;code&gt;JRouter&lt;/code&gt; will add it to the URL in the form of a query string (i.e. any variables that are not handled by the router will be passed in the query string).<br />
<br />
The prefix ''componentname'' is the name for your component, as found in the directory holding the component's files. For instance, a component &quot;Magic&quot; in directory &lt;tt&gt;/components/com_magic/...&lt;/tt&gt; would use a prefix &lt;code&gt;magic&lt;/code&gt; (all lower case).<br />
<br />
The next function in the &lt;tt&gt;router.php&lt;/tt&gt; parses the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute($segments)<br />
{<br />
$vars = array();<br />
switch($segments[0])<br />
{<br />
case 'categories':<br />
$vars['view'] = 'categories';<br />
break;<br />
case 'category':<br />
$vars['view'] = 'category';<br />
$id = explode(':', $segments[1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'article':<br />
$vars['view'] = 'article';<br />
$id = explode(':', $segments[1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
What happens here? In the function &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; we arranged the items in the &lt;code&gt;$query&lt;/code&gt; array in a specific sequence. This means that in this example the view is first and the id is second in the array.<br />
<br />
By reading &lt;code&gt;$segments[0]&lt;/code&gt;, we access the name of the view. We set the right view and/or identifier depending on its value and we return the &lt;code&gt;$vars&lt;/code&gt; array to &lt;code&gt;JRouter&lt;/code&gt;. &lt;code&gt;$vars&lt;/code&gt; should be an associative array similar to the array that was passed to the BuildRoute method.<br />
<br />
The above example of the &lt;tt&gt;router.php&lt;/tt&gt; is a very simple way to generate SEF URLs but should show how this works quite clearly.<br />
<br />
The generated URL in this example contains the name of the view and doesn't reflect the content hierarchy:<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[view]/[slug]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
=== A More Advanced Example ===<br />
<br />
In the next example we will try to get rid of the need for the view and we will try to reflect the current hierarchy level in the URL.<br />
<br />
The goal is URL's that look like:<br />
<br />
* When viewing an article: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]/[article]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing a category: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing the categories overview: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
Let's assume we have done step 1 and 2 also for the category.<br />
<br />
The link to the article would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_('index.php?view=article&amp;catid=' . $row-­&gt;catslug . '&amp;id='.$row-­&gt;slug);<br />
&lt;/source&gt;<br />
<br />
And the Link to the category would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_('index.php?view=category&amp;id=' . $row-&gt;catslug);<br />
&lt;/source&gt;<br />
<br />
The corresponding &lt;tt&gt;router.php&lt;/tt&gt;:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function [componentname]BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if (isset($query['catid']))<br />
{<br />
$segments[] = $query['catid'];<br />
unset($query['catid']);<br />
};<br />
if (isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset($query['id']);<br />
};<br />
unset($query['view']);<br />
return $segments;<br />
}<br />
&lt;/source&gt;<br />
<br />
The difference now is that we don’t add the name of the view to the &lt;code&gt;$segments&lt;/code&gt; array. We still unset the view key since otherwise, &lt;code&gt;JRouter&lt;/code&gt; would add it to the URL as part of the query string. Another new thing here is the additional parameter catid that we push into the &lt;code&gt;$segments&lt;/code&gt; array.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute($segments)<br />
{<br />
$vars = array();<br />
$app = JFactory::getApplication();<br />
$menu = $app-&gt;getMenu();<br />
$item = $menu-&gt;getActive();<br />
// Count segments<br />
$count = count($segments);<br />
// Handle View and Identifier<br />
switch ($item-&gt;query['view'])<br />
{<br />
case 'categories':<br />
if ($count == 1)<br />
{<br />
$vars['view'] = 'category';<br />
}<br />
if ($count == 2)<br />
{<br />
$vars['view'] = 'article';<br />
}<br />
$id = explode(':', $segments[$count-1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'category':<br />
$id = explode(':', $segments[$count-1]);<br />
$vars['id'] = (int) $id[0];<br />
$vars['view'] = 'article';<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
You can see that this ParseRoute function has a lot of different code parts in comparison to the previous. The reason for this is simple. We don’t have the name of the view in the &lt;code&gt;$segments&lt;/code&gt; array and we need to find another way to determine it.<br />
<br />
We need to find out which level of hierarchy we are in by receiving the root element. We do this by looking to the view name of the active menu item:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$item-­&gt;query['view']<br />
&lt;/source&gt;<br />
<br />
Also we need to know the number of items in the &lt;code&gt;$segments&lt;/code&gt; array:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$count = count($segments);<br />
&lt;/source&gt;<br />
<br />
With this information we can correctly set the view for all possible three cases:<br />
<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has two items (&lt;code&gt;$catid&lt;/code&gt; and &lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to an article.<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has one item (&lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to a category.<br />
* The menu item is a link to a category. In this case, we know that any item in the &lt;code&gt;$segments&lt;/code&gt; array is the identifier for an article.<br />
<br />
The result of all this code is clean and human-readable component URLs.<br />
<br />
== Routers and Menu Items ==<br />
<br />
A last important part of creating a router is considering what to do with menu items. As explained on [[Search Engine Friendly URLs]], the output of the component router is used ''after'' the first segment of a route, the first segment being the menu item's alias. This creates a difficult question: how is your router and/or other code to know which menu item to route through?<br />
<br />
Suppose, for example, that your component is currently producing output for the page &lt;tt&gt;/dogs&lt;/tt&gt;, which lists all dogs in the system. Of course, the items in the list need to be links to pages that display more details about one dog. What should the URL to the dog with ID 21 and name Fido become? Using a router that works according to the principles we've seen so far, the route that is produced is &lt;tt&gt;dogs/21-fido&lt;/tt&gt;, or with some additional work &lt;tt&gt;/dogs/fido&lt;/tt&gt;. But perhaps the user has created a menu item with the alias &lt;tt&gt;mydoggy&lt;/tt&gt; which displays exactly that dog's details. Then it is probably the user's intention to route this URL through that menu item, and the item in the list should link to the page &lt;tt&gt;/mydoggy&lt;/tt&gt;.<br />
<br />
More generally, whenever you are building a route, you will need to find the menu item that is most suitable as a ''starting point'' for building your route. The term ''starting point'' is emphasized because the rest of the route depends on the configuration of the menu item. In our example above, &lt;tt&gt;/dogs/21-fido&lt;/tt&gt; is an acceptable route, &lt;tt&gt;/mydoggy&lt;/tt&gt; is arguably even better, but &lt;tt&gt;/mydoggy/21-fido&lt;/tt&gt; is simply wrong, since &lt;tt&gt;/mydoggy&lt;/tt&gt; is in itself a menu item that is set up to display &lt;tt&gt;fido&lt;/tt&gt;'s information.<br />
<br />
Several approaches are available to tackle this problem. Joomla!'s core components take a mixed approach, separating responsibilities in two units of code: the router itself and the so-called &lt;code&gt;[componentname]RouteHelper&lt;/code&gt;. The &lt;code&gt;[componentname]RouteHelper&lt;/code&gt; provides methods that find the most suitable menu item for a given piece of data to be displayed, while the router analyzes the menu item and puts any information that is not determined by the menu item's configuration into the route. This does mean that the ''calling code'' must explicitly call the helper's method before routing (&lt;code&gt;echo JRoute::_(DogsRouteHelper::getDogRoute(21));&lt;/code&gt;).<br />
<br />
== See Also ==<br />
<br />
There is a useful thread on this subject here: [[jtopic:148632]] (note, may be out of date)<br />
<br />
For details on the internals of routing, see [[Routing implementation details]].<br />
&lt;noinclude&gt;[[Category:Tutorials]][[Category:Component Development]][[Category:Search Engine Friendly URLs]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Supporting_SEF_URLs_in_your_componentSupporting SEF URLs in your component2014-08-26T15:20:33Z<p>Mvangeest: Adjusted layout</p>
<hr />
<div>{{version/tutor|2.5,3.1}}<br />
{{:Search Engine Friendly URLs}}<br />
In Joomla!, each [[component]] is responsible for handling its own SEF URLs. Therefore, as the [[Developers|developer]] of a component, you will have to create your own '''router''' to allow your component to use SEF URLs.<br />
<br />
== The Concept ==<br />
<br />
Assuming you are following standard development practices, your component is probably using &quot;system URLs&quot; that look a lot like &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;, and your goal is to transform this into &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;. As the developer, you have two tasks: signalling the system that certain pieces of text are URLs and need to be transformed, and explaining the system how to transform URLs.<br />
<br />
=== Applying &lt;code&gt;JRoute::_&lt;/code&gt; ===<br />
<br />
It is difficult and inefficient for Joomla! to figure out which parts of your component's output are URLs. To support SEF URLs, you will need to change URL-generating code so that it applies &lt;code&gt;JRoute::_&lt;/code&gt; before outputting the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
echo JRoute::_('index.php?view=article&amp;id=1&amp;catid=20');<br />
&lt;/source&gt;<br />
<br />
Notice that it is possible to leave out the parameters &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;Itemid&lt;/code&gt;. &lt;code&gt;option&lt;/code&gt; defaults to the name of the component currently being executed, and &lt;code&gt;Itemid&lt;/code&gt; defaults to the current menu item's ID.<br />
<br />
In general, you should only apply this to URLs that users and/or search engines are able to see. For example, there is no need to transform URLs used in redirects that immediately result in other redirects.<br />
<br />
If the user turns off SEF URLs in the site's settings, &lt;code&gt;JRoute::_&lt;/code&gt; will produce working non-SEF URLs without any changes to the code.<br />
<br />
=== Writing a router ===<br />
<br />
You'll also need to write a router, which is a single file with two functions that convert system URLs to and from SEF URLs. This file needs to be placed at &lt;tt&gt;/components/com_yourcomponent/router.php&lt;/tt&gt;.<br />
<br />
The first function, &lt;code&gt;[componentname]BuildRoute(&amp;$query)&lt;/code&gt;, must transform an array of URL parameters into an array of segments that will form the SEF URL. Schematically, the transformation works as follows:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; &lt;code&gt;JRoute::_&lt;/code&gt;, called by your component or any other extension<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentBuildRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal route building (for display)<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
The second function, &lt;code&gt;[componentname]ParseRoute($segments)&lt;/code&gt;, must transform an array of segments back into an array of URL parameters. Schematically:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal route parsing<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentParseRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
The two functions must cooperate in such a way that the original URL can be reconstructed. You can think of &lt;code&gt;BuildRoute&lt;/code&gt; as a form of [[wikipedia:Encoding|encoding]] and &lt;code&gt;ParseRoute&lt;/code&gt; as the corresponding decoding. When the original URL isn't properly reproduced, your component will stop working.<br />
<br />
== Preparing Your Data for Routing ==<br />
<br />
=== The Alias ===<br />
<br />
The first step is the generation of the so called alias. The alias is used in the URL instead of the title (the alias is the text you want to have in the URL). The alias has to be URI safe, which means accented UTF­8 characters are replaced by their ASCII­7 equivalents, white spaces by hyphens, etc.<br />
<br />
The alias can be defined by the user, but you should ensure that the above requirements for a URL safe alias are met. A good way to do so is to use the &lt;code&gt;JTable::check()&lt;/code&gt; method during the save process. Have a look at this example code:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function check()<br />
{<br />
jimport('joomla.filter.output');<br />
if (empty($this-&gt;alias))<br />
{<br />
$this-&gt;alias = $this-&gt;title;<br />
}<br />
$this-&gt;alias = JFilterOutput::stringURLSafe($this-&gt;alias);<br />
<br />
/* All your other checks */<br />
return true;<br />
}<br />
&lt;/source&gt;<br />
<br />
If the alias field is empty the title will be used as alias. Then the alias will be made URLSafe using the &lt;code&gt;JFilterOutput::stringURLSafe()&lt;/code&gt; method.<br />
<br />
=== The Slug ===<br />
<br />
Continuing with the same example, the &quot;slug&quot; - &quot;1­:welcome­-to­-joomla&quot; has two parts. The first part is the article identifier (id) and the second is the alias. They are separated by a colon. These two elements were combined during the database query in the model:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$query = 'SELECT a.*, '.<br />
'CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(&quot;:&quot;, a.id, a.alias) ELSE a.id END as slug,'<br />
/*...*/;&lt;/source&gt;<br />
<br />
After this step the slug is used instead of the id.<br />
<br />
== Routing URLs ==<br />
<br />
The &lt;code&gt;JRoute::_&lt;/code&gt; method translates the internal Joomla! URL to a custom URL. &lt;code&gt;JRoute::_&lt;/code&gt; has three parameters and its prototype is:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_($url, $xhtml = true, $ssl = null);&lt;/source&gt;<br />
<br />
Where:<br />
<br />
* &lt;code&gt;$url&lt;/code&gt; is a string containing the absolute or relative internal Joomla! URL.<br />
* &lt;code&gt;$xhtml&lt;/code&gt; is a boolean value that specifies whether or not the output should be in XHTML. This parameter is optional and if omitted defaults to true.<br />
* &lt;code&gt;$ssl&lt;/code&gt; is an integer value that specifies whether the URI should be secure. It should be set to 1 to force the URI to be secure using the global secure site URI, 0 to leave it in the same state as when it was passed, and -1 to force the URI to be unsecure using the global unsecure site URI.<br />
<br />
The most important parameter is &lt;code&gt;$url&lt;/code&gt;. A call to this method might look like:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_('index.php?view=article&amp;id=' . $row-&gt;slug);&lt;/source&gt;<br />
<br />
&lt;code&gt;$row-­&gt;slug&lt;/code&gt; is the value that was generated in step 2 from a combination of id and title alias.<br />
<br />
Another advantage of using &lt;code&gt;JRoute::_&lt;/code&gt; is that the router now handles &lt;code&gt;$option&lt;/code&gt; (the component name) and the &lt;code&gt;$Itemid&lt;/code&gt; (the menu item ID). The component itself doesn't have to know its name (&lt;code&gt;$option&lt;/code&gt;) or the active menu item (&lt;code&gt;$Itemid&lt;/code&gt;) like it did in previous version of Joomla!.<br />
<br />
It is important that you think about the sequence of the URL parameter in this stage. This will be more clear when we have a deeper look at the &lt;tt&gt;router.php&lt;/tt&gt; in the next section.<br />
<br />
The building process of JRouter is divided into two steps:<br />
<br />
* Create the application route. The application route is fully handled by JRouter and the component developer doesn’t have to do anything to make it work.<br />
* Create the component route. To create the component route, JRouter looks for the &lt;tt&gt;router.php&lt;/tt&gt; in the component directory which is responsible for building the route for the component.<br />
<br />
== The Component Router ==<br />
<br />
We will have two functions in the &lt;tt&gt;router.php&lt;/tt&gt;. One is responsible for building the URL and the other is responsible for parsing it. In the next examples, a very basic and a more advanced one, we assume that we have three views that links can point to. The first is a categories overview (&lt;code&gt;view=categories&lt;/code&gt;), the second is a single category (&lt;code&gt;view=category&lt;/code&gt;) and the third is a single article (&lt;code&gt;view=article&lt;/code&gt;).<br />
<br />
The file &lt;tt&gt;router.php&lt;/tt&gt; should be in the site area of your component. It is not used on admin/backend pages. Don't forget to add it to your XML [[Manifest files|manifest file]] in the site folder.<br />
<br />
=== A Simple Example ===<br />
<br />
This simple example will illustrate the basics of implementing a router for your component.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if (isset($query['view']))<br />
{<br />
$segments[] = $query['view'];<br />
unset($query['view']);<br />
}<br />
if (isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset($query['id']);<br />
};<br />
return $segments;<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
&lt;code&gt;JRouter&lt;/code&gt; passes a &lt;code&gt;$query&lt;/code&gt; array to the &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; function. This function will add the relevant parts of the array to the $segments array in the right order and will return the properly ordered array. The content of the &lt;code&gt;$query&lt;/code&gt; array needs to be unset, otherwise &lt;code&gt;JRouter&lt;/code&gt; will add it to the URL in the form of a query string (i.e. any variables that are not handled by the router will be passed in the query string).<br />
<br />
The prefix ''componentname'' is the name for your component, as found in the directory holding the component's files. For instance, a component &quot;Magic&quot; in directory &lt;tt&gt;/components/com_magic/...&lt;/tt&gt; would use a prefix &lt;code&gt;magic&lt;/code&gt; (all lower case).<br />
<br />
The next function in the &lt;tt&gt;router.php&lt;/tt&gt; parses the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute($segments)<br />
{<br />
$vars = array();<br />
switch($segments[0])<br />
{<br />
case 'categories':<br />
$vars['view'] = 'categories';<br />
break;<br />
case 'category':<br />
$vars['view'] = 'category';<br />
$id = explode(':', $segments[1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'article':<br />
$vars['view'] = 'article';<br />
$id = explode(':', $segments[1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
What happens here? In the function &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; we arranged the items in the &lt;code&gt;$query&lt;/code&gt; array in a specific sequence. This means that in this example the view is first and the id is second in the array.<br />
<br />
By reading &lt;code&gt;$segments[0]&lt;/code&gt;, we access the name of the view. We set the right view and/or identifier depending on its value and we return the &lt;code&gt;$vars&lt;/code&gt; array to &lt;code&gt;JRouter&lt;/code&gt;. &lt;code&gt;$vars&lt;/code&gt; should be an associative array similar to the array that was passed to the BuildRoute method.<br />
<br />
The above example of the &lt;tt&gt;router.php&lt;/tt&gt; is a very simple way to generate SEF URLs but should show how this works quite clearly.<br />
<br />
The generated URL in this example contains the name of the view and doesn't reflect the content hierarchy:<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[view]/[slug]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
=== A More Advanced Example ===<br />
<br />
In the next example we will try to get rid of the need for the view and we will try to reflect the current hierarchy level in the URL.<br />
<br />
The goal is URL's that look like:<br />
<br />
* When viewing an article: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]/[article]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing a category: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing the categories overview: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
Let's assume we have done step 1 and 2 also for the category.<br />
<br />
The link to the article would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_('index.php?view=article&amp;catid=' . $row-­&gt;catslug . '&amp;id='.$row-­&gt;slug);<br />
&lt;/source&gt;<br />
<br />
And the Link to the category would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_('index.php?view=category&amp;id=' . $row-&gt;catslug);<br />
&lt;/source&gt;<br />
<br />
The corresponding &lt;tt&gt;router.php&lt;/tt&gt;:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function [componentname]BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if (isset($query['catid']))<br />
{<br />
$segments[] = $query['catid'];<br />
unset($query['catid']);<br />
};<br />
if (isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset($query['id']);<br />
};<br />
unset($query['view']);<br />
return $segments;<br />
}<br />
&lt;/source&gt;<br />
<br />
The difference now is that we don’t add the name of the view to the &lt;code&gt;$segments&lt;/code&gt; array. We still unset the view key since otherwise, &lt;code&gt;JRouter&lt;/code&gt; would add it to the URL as part of the query string. Another new thing here is the additional parameter catid that we push into the &lt;code&gt;$segments&lt;/code&gt; array.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute($segments)<br />
{<br />
$vars = array();<br />
$app = JFactory::getApplication();<br />
$menu = $app-&gt;getMenu();<br />
$item = $menu-&gt;getActive();<br />
// Count segments<br />
$count = count($segments);<br />
// Handle View and Identifier<br />
switch ($item-&gt;query['view'])<br />
{<br />
case 'categories':<br />
if ($count == 1)<br />
{<br />
$vars['view'] = 'category';<br />
}<br />
if ($count == 2)<br />
{<br />
$vars['view'] = 'article';<br />
}<br />
$id = explode(':', $segments[$count-1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'category':<br />
$id = explode(':', $segments[$count-1]);<br />
$vars['id'] = (int) $id[0];<br />
$vars['view'] = 'article';<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
You can see that this ParseRoute function has a lot of different code parts in comparison to the previous. The reason for this is simple. We don’t have the name of the view in the &lt;code&gt;$segments&lt;/code&gt; array and we need to find another way to determine it.<br />
<br />
We need to find out which level of hierarchy we are in by receiving the root element. We do this by looking to the view name of the active menu item:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$item-­&gt;query['view']<br />
&lt;/source&gt;<br />
<br />
Also we need to know the number of items in the &lt;code&gt;$segments&lt;/code&gt; array:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$count = count($segments);<br />
&lt;/source&gt;<br />
<br />
With this information we can correctly set the view for all possible three cases:<br />
<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has two items (&lt;code&gt;$catid&lt;/code&gt; and &lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to an article.<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has one item (&lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to a category.<br />
* The menu item is a link to a category. In this case, we know that any item in the &lt;code&gt;$segments&lt;/code&gt; array is the identifier for an article.<br />
<br />
The result of all this code is clean and human-readable component URLs.<br />
<br />
== Routers and Menu Items ==<br />
<br />
A last important part of creating a router is considering what to do with menu items. As explained on [[Search Engine Friendly URLs]], the output of the component router is used ''after'' the first segment of a route, the first segment being the menu item's alias. This creates a difficult question: how is your router and/or other code to know which menu item to route through?<br />
<br />
Suppose, for example, that your component is currently producing output for the page &lt;tt&gt;/dogs&lt;/tt&gt;, which lists all dogs in the system. Of course, the items in the list need to be links to pages that display more details about one dog. What should the URL to the dog with ID 21 and name Fido become? Using a router that works according to the principles we've seen so far, the route that is produced is &lt;tt&gt;dogs/21-fido&lt;/tt&gt;, or with some additional work &lt;tt&gt;/dogs/fido&lt;/tt&gt;. But perhaps the user has created a menu item with the alias &lt;tt&gt;mydoggy&lt;/tt&gt; which displays exactly that dog's details. Then it is probably the user's intention to route this URL through that menu item, and the item in the list should link to the page &lt;tt&gt;/mydoggy&lt;/tt&gt;.<br />
<br />
More generally, whenever you are building a route, you will need to find the menu item that is most suitable as a ''starting point'' for building your route. The term ''starting point'' is emphasized because the rest of the route depends on the configuration of the menu item. In our example above, &lt;tt&gt;/dogs/21-fido&lt;/tt&gt; is an acceptable route, &lt;tt&gt;/mydoggy&lt;/tt&gt; is arguably even better, but &lt;tt&gt;/mydoggy/21-fido&lt;/tt&gt; is simply wrong, since &lt;tt&gt;/mydoggy&lt;/tt&gt; is in itself a menu item that is set up to display &lt;tt&gt;fido&lt;/tt&gt;'s information.<br />
<br />
Several approaches are available to tackle this problem. Joomla!'s core components take a mixed approach, separating responsibilities in two units of code: the router itself and the so-called &lt;code&gt;[componentname]RouteHelper&lt;/code&gt;. The &lt;code&gt;[componentname]RouteHelper&lt;/code&gt; provides methods that find the most suitable menu item for a given piece of data to be displayed, while the router analyzes the menu item and puts any information that is not determined by the menu item's configuration into the route. This does mean that the ''calling code'' must explicitly call the helper's method before routing (&lt;code&gt;echo JRoute::_(DogsRouteHelper::getDogRoute(21));&lt;/code&gt;).<br />
<br />
== See Also ==<br />
<br />
There is a useful thread on this subject here: [[jtopic:148632]] (note, may be out of date)<br />
<br />
For details on the internals of routing, see [[Routing implementation details]].<br />
&lt;noinclude&gt;[[Category:Tutorials]][[Category:Component Development]][[Category:Search Engine Friendly URLs]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Supporting_SEF_URLs_in_your_componentSupporting SEF URLs in your component2014-08-26T15:13:22Z<p>Mvangeest: Adjusted code style</p>
<hr />
<div>{{version/tutor|2.5,3.1}}<br />
{{:Search Engine Friendly URLs}}<br />
In Joomla!, each [[component]] is responsible for handling its own SEF URLs. Therefore, as the [[Developers|developer]] of a component, you will have to create your own '''router''' to allow your component to use SEF URLs.<br />
<br />
== The Concept ==<br />
<br />
Assuming you are following standard development practices, your component is probably using &quot;system URLs&quot; that look a lot like &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;, and your goal is to transform this into &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;. As the developer, you have two tasks: signalling the system that certain pieces of text are URLs and need to be transformed, and explaining the system how to transform URLs.<br />
<br />
=== Applying &lt;code&gt;JRoute::_&lt;/code&gt; ===<br />
<br />
It is difficult and inefficient for Joomla! to figure out which parts of your component's output are URLs. To support SEF URLs, you will need to change URL-generating code so that it applies &lt;code&gt;JRoute::_&lt;/code&gt; before outputting the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
echo JRoute::_('index.php?view=article&amp;id=1&amp;catid=20');<br />
&lt;/source&gt;<br />
<br />
Notice that it is possible to leave out the parameters &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;Itemid&lt;/code&gt;. &lt;code&gt;option&lt;/code&gt; defaults to the name of the component currently being executed, and &lt;code&gt;Itemid&lt;/code&gt; defaults to the current menu item's ID.<br />
<br />
In general, you should only apply this to URLs that users and/or search engines are able to see. For example, there is no need to transform URLs used in redirects that immediately result in other redirects.<br />
<br />
If the user turns off SEF URLs in the site's settings, &lt;code&gt;JRoute::_&lt;/code&gt; will produce working non-SEF URLs without any changes to the code.<br />
<br />
=== Writing a router ===<br />
<br />
You'll also need to write a router, which is a single file with two functions that convert system URLs to and from SEF URLs. This file needs to be placed at &lt;tt&gt;/components/com_yourcomponent/router.php&lt;/tt&gt;.<br />
<br />
The first function, &lt;code&gt;[componentname]BuildRoute(&amp;$query)&lt;/code&gt;, must transform an array of URL parameters into an array of segments that will form the SEF URL. Schematically, the transformation works as follows:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; &lt;code&gt;JRoute::_&lt;/code&gt;, called by your component or any other extension<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentBuildRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal route building (for display)<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
The second function, &lt;code&gt;[componentname]ParseRoute($segments)&lt;/code&gt;, must transform an array of segments back into an array of URL parameters. Schematically:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal route parsing<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentParseRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
The two functions must cooperate in such a way that the original URL can be reconstructed. You can think of &lt;code&gt;BuildRoute&lt;/code&gt; as a form of [[wikipedia:Encoding|encoding]] and &lt;code&gt;ParseRoute&lt;/code&gt; as the corresponding decoding. When the original URL isn't properly reproduced, your component will stop working.<br />
<br />
== Preparing Your Data for Routing ==<br />
<br />
=== The Alias ===<br />
<br />
The first step is the generation of the so called alias. The alias is used in the URL instead of the title (the alias is the text you want to have in the URL). The alias has to be URI safe, which means accented UTF­8 characters are replaced by their ASCII­7 equivalents, white spaces by hyphens, etc.<br />
<br />
The alias can be defined by the user, but you should ensure that the above requirements for a URL safe alias are met. A good way to do so is to use the JTable::check() method during the save process. Have a look at this example code:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function check()<br />
{<br />
jimport('joomla.filter.output');<br />
if (empty($this-&gt;alias))<br />
{<br />
$this-&gt;alias = $this-&gt;title;<br />
}<br />
$this-&gt;alias = JFilterOutput::stringURLSafe($this-&gt;alias);<br />
<br />
/* All your other checks */<br />
return true;<br />
}<br />
&lt;/source&gt;<br />
<br />
If the alias field is empty the title will be used as alias. Then the alias will be made URLSafe using the &lt;code&gt;JFilterOutput::stringURLSafe()&lt;/code&gt; method.<br />
<br />
=== The Slug ===<br />
<br />
Continuing with the same example, the &quot;slug&quot; - &quot;1­:welcome­-to­-joomla&quot; has two parts. The first part is the article identifier (id) and the second is the alias. They are separated by a colon. These two elements were combined during the database query in the model:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$query = 'SELECT a.*, '.<br />
'CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(&quot;:&quot;, a.id, a.alias) ELSE a.id END as slug,'<br />
/*...*/;&lt;/source&gt;<br />
<br />
After this step the slug is used instead of the id.<br />
<br />
== Routing URLs ==<br />
<br />
The &lt;code&gt;JRoute::_&lt;/code&gt; method translates the internal Joomla! URL to a custom URL. &lt;tt&gt;JRoute&lt;/tt&gt; has three parameters and its prototype is:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_($url, $xhtml = true, $ssl = null);&lt;/source&gt;<br />
<br />
Where:<br />
<br />
* &lt;code&gt;$url&lt;/code&gt; is a string containing the absolute or relative internal Joomla! URL.<br />
* &lt;code&gt;$xhtml&lt;/code&gt; is a boolean value that specifies whether or not the output should be in XHTML. This parameter is optional and if omitted defaults to true.<br />
* &lt;code&gt;$ssl&lt;/code&gt; is an integer value that specifies whether the URI should be secure. It should be set to 1 to force the URI to be secure using the global secure site URI, 0 to leave it in the same state as when it was passed, and -1 to force the URI to be unsecure using the global unsecure site URI.<br />
<br />
The most important parameter is &lt;code&gt;$url&lt;/code&gt;. A call to this method might look like:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_('index.php?view=article&amp;id=' . $row-&gt;slug);&lt;/source&gt;<br />
<br />
&lt;code&gt;$row-­&gt;slug&lt;/code&gt; is the value that was generated in step 2 from a combination of id and title alias.<br />
<br />
Another advantage of using JRoute is that the router now handles $option (the component name) and the $Itemid (the menu item ID). The component itself doesn’t have to know its name ($option) or the active menu item ($Itemid) like it did in previous version of Joomla!.<br />
<br />
It is important that you think about the sequence of the URL parameter in this stage. This will be more clear when we have a deeper look at the router.php in the next section.<br />
<br />
The building process of JRouter is divided into two steps:<br />
<br />
* Create the application route. The application route is fully handled by JRouter and the component developer doesn’t have to do anything to make it work.<br />
* Create the component route. To create the component route, JRouter looks for the &lt;tt&gt;router.php&lt;/tt&gt; in the component directory which is responsible for building the route for the component.<br />
<br />
== The Component Router ==<br />
<br />
We will have two functions in the &lt;tt&gt;router.php&lt;/tt&gt;. One is responsible for building the URL and the other is responsible for parsing it. In the next examples, a very basic and a more advanced one, we assume that we have three views that links can point to. The first is a categories overview (&lt;code&gt;view=categories&lt;/code&gt;), the second is a single category (&lt;code&gt;view=category&lt;/code&gt;) and the third is a single article (&lt;code&gt;view=article&lt;/code&gt;).<br />
<br />
The file &lt;tt&gt;router.php&lt;/tt&gt; should be in the site area of your component. It is not used on admin/backend pages. Don't forget to add it to your XML [[Manifest files|manifest file]] in the site folder.<br />
<br />
=== A Simple Example ===<br />
<br />
This simple example will illustrate the basics of implementing a router for your component.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if (isset($query['view']))<br />
{<br />
$segments[] = $query['view'];<br />
unset($query['view']);<br />
}<br />
if (isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset($query['id']);<br />
};<br />
return $segments;<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
&lt;code&gt;JRouter&lt;/code&gt; passes a $query array to the &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; function. This function will add the relevant parts of the array to the $segments array in the right order and will return the properly ordered array. The content of the &lt;code&gt;$query&lt;/code&gt; array needs to be unset, otherwise &lt;code&gt;JRouter&lt;/code&gt; will add it to the URL in the form of a query string (i.e. any variables that are not handled by the router will be passed in the query string).<br />
<br />
The prefix ''componentname'' is the name for your component, as found in the directory holding the component's files. For instance, a component &quot;Magic&quot; in directory &lt;tt&gt;/components/com_magic/...&lt;/tt&gt; would use a prefix &lt;code&gt;magic&lt;/code&gt; (all lower case).<br />
<br />
The next function in the &lt;tt&gt;router.php&lt;/tt&gt; parses the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute($segments)<br />
{<br />
$vars = array();<br />
switch($segments[0])<br />
{<br />
case 'categories':<br />
$vars['view'] = 'categories';<br />
break;<br />
case 'category':<br />
$vars['view'] = 'category';<br />
$id = explode(':', $segments[1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'article':<br />
$vars['view'] = 'article';<br />
$id = explode(':', $segments[1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
What happens here? In the function &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; we arranged the items in the &lt;code&gt;$query&lt;/code&gt; array in a specific sequence. This means that in this example the view is first and the id is second in the array.<br />
<br />
By reading &lt;code&gt;$segments[0]&lt;/code&gt;, we access the name of the view. We set the right view and/or identifier depending on its value and we return the &lt;code&gt;$vars&lt;/code&gt; array to &lt;code&gt;JRouter&lt;/code&gt;. $vars should be an associative array similar to the array that was passed to the BuildRoute method.<br />
<br />
The above example of the &lt;tt&gt;router.php&lt;/tt&gt; is a very simple way to generate SEF URLs but should show how this works quite clearly.<br />
<br />
The generated URL in this example contains the name of the view and doesn't reflect the content hierarchy:<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[view]/[slug]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
=== A More Advanced Example ===<br />
<br />
In the next example we will try to get rid of the need for the view and we will try to reflect the current hierarchy level in the URL.<br />
<br />
The goal is URL's that look like:<br />
<br />
* When viewing an article: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]/[article]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing a category: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing the categories overview: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
Let's assume we have done step 1 and 2 also for the category.<br />
<br />
The link to the article would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_('index.php?view=article&amp;catid=' . $row-­&gt;catslug . '&amp;id='.$row-­&gt;slug);<br />
&lt;/source&gt;<br />
<br />
And the Link to the category would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_('index.php?view=category&amp;id=' . $row-&gt;catslug);<br />
&lt;/source&gt;<br />
<br />
The corresponding &lt;tt&gt;router.php&lt;/tt&gt;:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function [componentname]BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if (isset($query['catid']))<br />
{<br />
$segments[] = $query['catid'];<br />
unset($query['catid']);<br />
};<br />
if (isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset($query['id']);<br />
};<br />
unset($query['view']);<br />
return $segments;<br />
}<br />
&lt;/source&gt;<br />
<br />
The difference now is that we don’t add the name of the view to the &lt;code&gt;$segments&lt;/code&gt; array. We still unset the view key since otherwise, &lt;code&gt;JRouter&lt;/code&gt; would add it to the URL as part of the query string. Another new thing here is the additional parameter catid that we push into the &lt;code&gt;$segments&lt;/code&gt; array.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute($segments)<br />
{<br />
$vars = array();<br />
$app = JFactory::getApplication();<br />
$menu = $app-&gt;getMenu();<br />
$item = $menu-&gt;getActive();<br />
// Count segments<br />
$count = count($segments);<br />
// Handle View and Identifier<br />
switch ($item-&gt;query['view'])<br />
{<br />
case 'categories':<br />
if ($count == 1)<br />
{<br />
$vars['view'] = 'category';<br />
}<br />
if ($count == 2)<br />
{<br />
$vars['view'] = 'article';<br />
}<br />
$id = explode(':', $segments[$count-1]);<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'category':<br />
$id = explode(':', $segments[$count-1]);<br />
$vars['id'] = (int) $id[0];<br />
$vars['view'] = 'article';<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
You can see that this ParseRoute function has a lot of different code parts in comparison to the previous. The reason for this is simple. We don’t have the name of the view in the &lt;code&gt;$segments&lt;/code&gt; array and we need to find another way to determine it.<br />
<br />
We need to find out which level of hierarchy we are in by receiving the root element. We do this by looking to the view name of the active menu item:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$item-­&gt;query['view']<br />
&lt;/source&gt;<br />
<br />
Also we need to know the number of items in the &lt;code&gt;$segments&lt;/code&gt; array:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$count = count($segments);<br />
&lt;/source&gt;<br />
<br />
With this information we can correctly set the view for all possible three cases:<br />
<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has two items (&lt;code&gt;$catid&lt;/code&gt; and &lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to an article.<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has one item (&lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to a category.<br />
* The menu item is a link to a category. In this case, we know that any item in the &lt;code&gt;$segments&lt;/code&gt; array is the identifier for an article.<br />
<br />
The result of all this code is clean and human-readable component URLs.<br />
<br />
== Routers and Menu Items ==<br />
<br />
A last important part of creating a router is considering what to do with menu items. As explained on [[Search Engine Friendly URLs]], the output of the component router is used ''after'' the first segment of a route, the first segment being the menu item's alias. This creates a difficult question: how is your router and/or other code to know which menu item to route through?<br />
<br />
Suppose, for example, that your component is currently producing output for the page &lt;tt&gt;/dogs&lt;/tt&gt;, which lists all dogs in the system. Of course, the items in the list need to be links to pages that display more details about one dog. What should the URL to the dog with ID 21 and name Fido become? Using a router that works according to the principles we've seen so far, the route that is produced is &lt;tt&gt;dogs/21-fido&lt;/tt&gt;, or with some additional work &lt;tt&gt;/dogs/fido&lt;/tt&gt;. But perhaps the user has created a menu item with the alias &lt;tt&gt;mydoggy&lt;/tt&gt; which displays exactly that dog's details. Then it is probably the user's intention to route this URL through that menu item, and the item in the list should link to the page &lt;tt&gt;/mydoggy&lt;/tt&gt;.<br />
<br />
More generally, whenever you are building a route, you will need to find the menu item that is most suitable as a ''starting point'' for building your route. The term ''starting point'' is emphasized because the rest of the route depends on the configuration of the menu item. In our example above, &lt;tt&gt;/dogs/21-fido&lt;/tt&gt; is an acceptable route, &lt;tt&gt;/mydoggy&lt;/tt&gt; is arguably even better, but &lt;tt&gt;/mydoggy/21-fido&lt;/tt&gt; is simply wrong, since &lt;tt&gt;/mydoggy&lt;/tt&gt; is in itself a menu item that is set up to display &lt;tt&gt;fido&lt;/tt&gt;'s information.<br />
<br />
Several approaches are available to tackle this problem. Joomla!'s core components take a mixed approach, separating responsibilities in two units of code: the router itself and the so-called &lt;code&gt;[componentname]RouteHelper&lt;/code&gt;. The &lt;code&gt;[componentname]RouteHelper&lt;/code&gt; provides methods that find the most suitable menu item for a given piece of data to be displayed, while the router analyzes the menu item and puts any information that is not determined by the menu item's configuration into the route. This does mean that the ''calling code'' must explicitly call the helper's method before routing (&lt;code&gt;echo JRoute::_(DogsRouteHelper::getDogRoute(21));&lt;/code&gt;).<br />
<br />
== See Also ==<br />
<br />
There is a useful thread on this subject here: [[jtopic:148632]] (note, may be out of date)<br />
<br />
For details on the internals of routing, see [[Routing implementation details]].<br />
&lt;noinclude&gt;[[Category:Tutorials]][[Category:Component Development]][[Category:Search Engine Friendly URLs]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Manifest_filesManifest files2014-07-07T22:54:25Z<p>Mvangeest: Fixed layout</p>
<hr />
<div>{{version|2.5,3.x}}<br />
<br />
Within Joomla there are manifest files for all of the extensions. These files include the general installation information as well as parameters for the configuration of the [[extension]] itself. Since Joomla! 2.5 {{JVer|2.5}}, there are very few differences between the manifest file formats for the different [[Extension types (technical definitions)|types of extensions]], allowing each type to access the full power of the Joomla! installer.<br />
<br />
==Naming conventions==<br />
The file must be named &lt;tt&gt;manifest.xml&lt;/tt&gt; or &lt;tt&gt;&lt;extension_name&gt;.xml&lt;/tt&gt; and located in the root directory of the installation package.<br />
<br />
==Syntax==<br />
<br />
=== Root element ===<br />
The primary tag of the installation file is: <br />
&lt;source lang=xml&gt;&lt;extension&gt;&lt;/extension&gt;&lt;/source&gt;<br />
<br />
This starting and closing tags are now valid for all extensions. The new tag &lt;code&gt;&lt;extension&gt;&lt;/code&gt; replaces the old &lt;code&gt;&lt;install&gt;&lt;/install&gt;&lt;/code&gt; from Joomla {{JVer|1.5}}. The following attributes are allowed within the tag:<br />
<br />
{|class=&quot;wikitable&quot;<br />
|-<br />
! style=&quot;width: 150px&quot; | Attribute || style=&quot;width: 150px&quot; | Values || Applicable&amp;nbsp;to || Description<br />
|-<br />
| type || &lt;code&gt;component&lt;/code&gt;&lt;br /&gt;&lt;code&gt;file&lt;/code&gt;&lt;br /&gt;&lt;code&gt;language&lt;/code&gt;&lt;br /&gt;&lt;code&gt;library&lt;/code&gt;&lt;br /&gt;&lt;code&gt;module&lt;/code&gt;&lt;br /&gt;&lt;code&gt;package&lt;/code&gt;&lt;br /&gt;&lt;code&gt;plugin&lt;/code&gt;&lt;br /&gt;&lt;code&gt;template&lt;/code&gt; || All extensions<br />
| This attribute describes the type of the extension for the installer. Based on this type further requirements to sub-tags apply.<br />
|-<br />
| version<br />
| &lt;code&gt;2.5&lt;/code&gt;&lt;br /&gt;&lt;code&gt;3.0&lt;/code&gt; || All extensions<br />
| String that identifies the version of Joomla for which this extension is developed.<br />
|-<br />
| method<br />
| &lt;code&gt;install&lt;/code&gt;&lt;br /&gt;&lt;code&gt;upgrade&lt;/code&gt; || All extensions<br />
| The default value &lt;code&gt;install&lt;/code&gt; will be also used if the method attribute is not used. The &lt;code&gt;install&lt;/code&gt; value means the installer will gracefully stop if it finds any existing file/folder of the new extension.<br />
|-<br />
| client<br />
| &lt;code&gt;site&lt;/code&gt;&lt;br /&gt;&lt;code&gt;administrator&lt;/code&gt; || Modules<br />
| The client attribute allows you to specify for which application client the new module is available.<br />
|-<br />
| group<br />
| ''string'' || Plugins<br />
| The group name specifies for which group of plugins the new plugin is available. The existing groups are the folder names within the directory &lt;tt&gt;/plugins&lt;/tt&gt;. The installer will create new folder names for group names that do not exist yet.<br />
|}<br />
<br />
<br />
=== Metadata ===<br />
<br />
The following elements can be used to insert metadata. None of these elements are required; if they are present, they must be a child of the root element.<br />
<br />
&lt;pre&gt;<br />
&lt;name&gt; &amp;ndash; raw component name (e.g. com_banners). <br />
&lt;author&gt; &amp;ndash; author's name (e.g. Joomla! Project)<br />
&lt;creationDate&gt; &amp;ndash; date of creation or release (e.g. April 2006)<br />
&lt;copyright&gt; &amp;ndash; a copyright statement (e.g. (C) 2005 - 2011 Open Source Matters. All rights reserved.)<br />
&lt;license&gt; &amp;ndash; a license statement (e.g. NU General Public License version 2 or later; see LICENSE.txt)<br />
&lt;authorEmail&gt; &amp;ndash; author's email address (e.g. admin@joomla.org)<br />
&lt;authorUrl&gt; &amp;ndash; URL to the author's website (e.g. www.joomla.org)<br />
&lt;version&gt; &amp;ndash; the version number of the extension (e.g. 1.6.0)<br />
&lt;description&gt; &amp;ndash; the description of the component. This is a translatable field. (e.g. COM_BANNERS_XML_DESCRIPTION)<br />
&lt;/pre&gt;<br />
<br />
Note: The &lt;name&gt; and &lt;description&gt; tags are also translatable fields so that the name and description of the extension can be shown to the user in their native language.<br />
<br />
=== Front-end files ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files folder=&quot;from-folder&quot;&gt;<br />
&lt;filename&gt;example.php&lt;/filename&gt;<br />
&lt;folder&gt;examples&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;/source&gt;<br />
<br />
Files to copy to the front-end directory should be placed in the &lt;code&gt;&lt;files&gt;&lt;/code&gt; element. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from'''. Each file to copy must be represented by a &lt;code&gt;&lt;filename&gt;&lt;/code&gt; element. If you want to copy an entire folder at once, you can define it as a &lt;code&gt;&lt;folder&gt;&lt;/code&gt;.<br />
<br />
=== Media files ===<br />
<br />
&lt;source lang=&quot;xml&gt;<br />
&lt;media folder=&quot;media&quot; destination=&quot;com_example&quot;&gt;<br />
&lt;filename&gt;com_example_logo.png&lt;/filename&gt;<br />
&lt;folder&gt;css&lt;/folder&gt;<br />
&lt;folder&gt;js&lt;/folder&gt;<br />
&lt;/media&gt;<br />
&lt;/source&gt;<br />
<br />
This example will copy the file(s) (&lt;tt&gt;/media/com_example_logo.png&lt;/tt&gt;) and folders ( &lt;tt&gt;/media/css/&lt;/tt&gt; and &lt;tt&gt;/media/js/&lt;/tt&gt; ) listed to &lt;tt&gt;/media/com_example/&lt;/tt&gt;, creating the &lt;tt&gt;com_example&lt;/tt&gt; folder if required. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from''' (in this case, &lt;tt&gt;media&lt;/tt&gt;).<br />
<br />
Extensions should be storing assets they need to be web accessible (JS, CSS, images etc) in &lt;code&gt;media&lt;/code&gt;. Amongst other things this feature was added as step in the progression to multi-site support and the eventual move of code files (PHP) out of the web accessible areas of the server.<br />
<br />
Ref:<br />
* [https://groups.google.com/forum/#!msg/joomla-dev-cms/4CAASJqFY-k/PvPj14gP29EJ Google Groups - joomla-dev-cms thread]<br />
* [https://groups.google.com/forum/#!msg/joomla-dev-cms/uNmhX98sKbE/p8p68Jke680J Google Groups - joomla-dev-cms thread]<br />
<br />
=== Administration section ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;administration&gt;<br />
&lt;!-- various elements --&gt;<br />
&lt;/administration&gt;<br />
&lt;/source&gt;<br />
<br />
The administration section is defined in the &lt;code&gt;&lt;administration&gt;&lt;/code&gt; element. Since only [[Component|components]] apply to both the [[Site (Application)|site]] and the [[Administrator (Application)|administrator]], '''only component manifests can include this element'''.<br />
<br />
==== Back-end files ====<br />
<br />
Files to copy to the back-end directory should be placed in the &lt;code&gt;&lt;files&gt;&lt;/code&gt; element under the &lt;code&gt;&lt;administration&gt;&lt;/code&gt;. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from'''. See ''Front-end files'' for further rules.<br />
<br />
==== Menu links and submenus ====<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;menu&gt;COM_EXAMPLE&lt;/menu&gt;<br />
&lt;submenu&gt;<br />
&lt;menu link=&quot;anoption=avalue&quot;&gt;COM_EXAMPLE_SUBMENU_ANOPTION&lt;/menu&gt;<br />
&lt;menu view=&quot;viewname&quot;&gt;COM_EXAMPLE_SUBMENU_VIEWNAME&lt;/menu&gt;<br />
&lt;/submenu&gt;<br />
&lt;/source&gt;<br />
<br />
The text for the main menu item for the component is defined in the &lt;code&gt;&lt;menu&gt;&lt;/code&gt; item, a child of &lt;code&gt;&lt;administration&gt;&lt;/code&gt;. A &lt;code&gt;&lt;submenu&gt;&lt;/code&gt; element may also be present (also a child of &lt;code&gt;&lt;administration&gt;&lt;/code&gt;), which may contain more menu items defined by &lt;code&gt;&lt;menu&gt;&lt;/code&gt;.<br />
<br />
Additionally, each &lt;code&gt;&lt;menu&gt;&lt;/code&gt; item can define the following attributes:<br />
<br />
{| class=&quot;wikitable&quot;<br />
! style=&quot;width: 150px&quot; | Attribute || Description<br />
|-<br />
| link || A link to send the user to when the menu item is clicked<br />
|-<br />
| img || The (relative) path to an image (16x16 pixels) to appear beside the menu item. <br />
&lt;u&gt;Must be an url compatible as a file too (e.g. no spaces) !&lt;/u&gt;<br />
|-<br />
| alt ||<br />
|-<br />
| ''string'' || An URL parameter to add to the link. For example, &lt;code&gt;&lt;menu view=&quot;cpanel&quot;&gt;COM_EXAMPLE&lt;/menu&gt;&lt;/code&gt; in com_example's XML manifest would cause the URL of the menu item to be &lt;tt&gt;index.php?option=com_example&amp;view=cpanel&lt;/tt&gt;.<br />
|-<br />
|}<br />
<br />
The value inside the tag is the menu's label. Unlike Joomla! 1.5, you can not use a natural language string. For example, if you would enter &quot;Example Component&quot; instead of COM_EXAMPLE, it would result in your component name appearing as example-component in the menu and you would be unable to provide a translation. In order to provide a translation you need to create a file named en-GB.com_example.sys.ini in administrator/languages/en-GB (you can use the manifest's &lt;code&gt;&amp;lt;languages&amp;gt;&lt;/code&gt; tag to copy it during installation) or in administrator/components/com_example/language/en-GB. In the latter case, you must not include the translation file in the &lt;code&gt;&amp;lt;languages&amp;gt;&lt;/code&gt; tag. As long as you have placed the language directory in your &lt;code&gt;&lt;files&gt;&lt;/code&gt; tag, it will be copied along when the component is being installed.<br />
<br />
The contents of that file should be:<br />
&lt;source&gt;<br />
COM_EXAMPLE=&quot;Example Component&quot;<br />
COM_EXAMPLE_SUBMENU_ANOPTION=&quot;Another Option&quot;<br />
COM_EXAMPLE_SUBMENU_VIEWNAME=&quot;Another View&quot;<br />
<br />
&lt;/source&gt;<br />
<br />
Please note that the language string must be enclosed in double quotes, as per Joomla!'s translation standards. Important note: Joomla! 1.6 and later sorts the Component menu items based on the actual translation of the key you supply in your XML manifest. This means that the sorting order is correct no matter what you call your translation key and no matter which language the site is being displayed in. Essentially, Joomla! 1.6 fixed the wrong sorting of the Components menu experienced under Joomla! 1.5 for the majority (non-English speaking!) of Joomla! users.<br />
<br />
{{Needsinfo|In Platform 11.1 no alt attribute processed and if link provide in menu tag other provided attributes were ignore. The other tags are task, view, controller, act, layout, sub. Please confirm this, please.}}<br />
<br />
=== Configuration ===<br />
{{warning|Components '''do not support''' configuration definitions '''in the manifest'''. This is a way implemented in Joomla! 1.5. They can define configuration options for multiple levels using [[Component configuration metadata]].}}<br />
The &lt;code&gt;&lt;config&gt;&lt;/code&gt; element, a child of the root, describes the configuration options for the extension. If applicable, the options will be shown by the appropriate Manager (Plugin Manager, Module Manager or Template Manager). '''Configuration options can also be defined in a separate file named &lt;code&gt;config.xml&lt;/code&gt;. Its root element should be &lt;code&gt;&lt;config&gt;&lt;/code&gt;.'''<br />
<br />
{{:XML JForm form definitions}}<br />
<br />
=== SQL ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;install folder=&quot;admin&quot;&gt;<br />
&lt;sql&gt;<br />
&lt;file driver=&quot;mysql&quot; charset=&quot;utf8&quot;&gt;sql/example.install.sql&lt;/file&gt;<br />
&lt;/sql&gt;<br />
&lt;/install&gt;<br />
&lt;uninstall folder=&quot;admin&quot;&gt;<br />
&lt;sql&gt;<br />
&lt;file driver=&quot;mysql&quot; charset=&quot;utf8&quot;&gt;sql/example.uninstall.sql&lt;/file&gt;<br />
&lt;/sql&gt;<br />
&lt;/uninstall&gt;<br />
&lt;/source&gt;<br />
<br />
In the above example, we put the SQL files in the &quot;admin/sql&quot; folder of the installation package. You have to include the &quot;sql&quot; folder in the administration files.<br />
<br />
You can execute SQL during the installation and/or uninstallation using the &lt;code&gt;&lt;install&gt;&lt;/code&gt; and &lt;code&gt;&lt;uninstall&gt;&lt;/code&gt; elements, respectively. A &lt;code&gt;&lt;sql&gt;&lt;/code&gt; element should appear as a child of these elements. &lt;code&gt;&lt;sql&gt;&lt;/code&gt; can contain any number of &lt;code&gt;&lt;file&gt;&lt;/code&gt; elements, each defining a single SQL file to execute. Their database driver types are described by the &lt;code&gt;driver&lt;/code&gt; attribute, their character sets by the &lt;code&gt;charset&lt;/code&gt; attribute.<br />
<br />
==== Update of the SQL schema ====<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;update&gt;<br />
&lt;schemas&gt;<br />
&lt;schemapath type=&quot;mysql&quot;&gt;sql/updates/mysql&lt;/schemapath&gt;<br />
&lt;schemapath type=&quot;sqlsrv&quot;&gt;sql/updates/sqlsrv&lt;/schemapath&gt;<br />
&lt;/schemas&gt;<br />
&lt;/update&gt;<br />
&lt;/source&gt;<br />
<br />
Since 1.6, there is also an &lt;code&gt;&lt;update&gt;&lt;/code&gt; tag, which allows you to provide a series of SQL files to update the current schema.<br />
<br />
=== Language files ===<br />
In Joomla! 1.5, extension developers had to put extension language files in the Joomla! main language file, using the &lt;languages&gt;..&lt;/languages&gt; tag as shown below. '''This method can still be used in''' {{rarr|2.5,3.x}}.<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;!-- Joomla! 1.5 language tag --&gt;<br />
&lt;languages folder=&quot;langfiles&quot;&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;en-GB.com_example.ini&lt;/language&gt;<br />
&lt;/languages&gt;<br />
&lt;/source&gt;<br />
<br />
Since Joomla! 1.6 it has been encouraged placing your extension's language files in your extension folder. Joomla! will then automatically load your extension's language files.<br />
<br />
By storing extension language files in the extension folder, you gain the benefit of isolating and protecting your extension's language files. For example, an administrator removes a language from their Joomla! installation. Your extension's language files will not be removed. They will remain in place and will be available if the language is installed again.<br />
<br />
The structure of the language folder for frontend and backend is the same. You put them in the language tag (e.g. '''en-GB''' ) of each language in your language folder i.e. '''language/en-GB/'''. You have to specify those folders in the front-end and back-end files too.<br />
<br />
In your manifest you simply include the ''''language'''' folder in your files section, the sub-directories for each language automatically be copied. Inside the &lt;files&gt; group you simply add a &lt;folder&gt; element alongside the items in the '''&lt;files&gt;''' group as shown in this example:<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files&gt;<br />
&lt;filename plugin=&quot;alpha&quot;&gt;alpha.php&lt;/filename&gt;<br />
&lt;folder&gt;sql&lt;/folder&gt;<br />
&lt;folder&gt;language&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;/source&gt;<br />
<br />
It is also notable that both ways can work together. Here is an example from core:<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files&gt;<br />
&lt;filename plugin=&quot;languagecode&quot;&gt;languagecode.php&lt;/filename&gt;<br />
&lt;filename&gt;index.html&lt;/filename&gt;<br />
&lt;folder&gt;language&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;languages&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;language/en-GB/en-GB.plg_system_languagecode.ini&lt;/language&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;language/en-GB/en-GB.plg_system_languagecode.sys.ini&lt;/language&gt;<br />
&lt;/languages&gt;<br />
&lt;/source&gt;<br />
<br />
The advantages of this solution are the following:<br />
<br />
All ini files present in the core folder have precedence over the files in the extension language/ folder.<br />
For example a sys.ini file will always be loaded from core folders in back-end if it exists, except when installing an extension which contains a sys.ini file in a language folder. In that case and only that case, the sys.ini file in the extension folder will display its translated content at install time. This is very handy as a developer can have 2 sys.ini files with different contents. A description of the successful install as well as a tutorial in back-end for example.<br />
<br />
Also, it is much easier for a user needing an ini file for an extension that does not provide it in the language desired, to add it in the main folders. No risk for it to be deleted in case of uninstalling the extension by mistake or any other reason.<br />
<br />
See also:<br />
*[[J2.5:Making non-core language packs|Making non-core language packs]]<br />
*[[Creating language packs for extensions in Joomla 2.5]]<br />
<br />
During development you can turn on language debugging in the Joomla! global configuration. So you can investigate if a problems arises. As of 3.2, this is necessary to help debug as en-GB is '''always''' loaded first when not in debug mode to prevent displaying Constants.<br />
<br />
=== Script file ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;scriptfile&gt;example.script.php&lt;/scriptfile&gt;<br />
&lt;/source&gt;<br />
<br />
An optional '''script file''' (PHP code that is run before, during and/or after installation, uninstallation and upgrading) can be defined using a &lt;code&gt;&lt;scriptfile&gt;&lt;/code&gt; element. This file should contain a class named &quot;&lt;element_name&gt;IntallerScript&quot; where &lt;element_name&gt; is the name of your extension (e.g. com_componentname, mod_modulename, etc.). Plugins requires to state the group (e.g. plgsystempluginname). Library packages do not support scriptfiles. The structure of the class is as follows:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
class com_componentnameInstallerScript<br />
{<br />
/**<br />
* Constructor<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*/<br />
public function __construct(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called before any type of action<br />
*<br />
* @param string $route Which action is happening (install|uninstall|discover_install|update)<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function preflight($route, JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called after any type of action<br />
*<br />
* @param string $route Which action is happening (install|uninstall|discover_install|update)<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function postflight($route, JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on installation<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function install(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on update<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function update(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on uninstallation<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*/<br />
public function uninstall(JAdapterInstance $adapter);<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
=== Update servers ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;updateservers&gt;<br />
&lt;server type=&quot;extension&quot; priority=&quot;1&quot; name=&quot;Extension Update Site&quot;&gt;http://example.com/extension.xml&lt;/server&gt;<br />
&lt;server type=&quot;collection&quot; priority=&quot;2&quot; name=&quot;Collection Update Site&quot;&gt;http://example.com/collection.xml&lt;/server&gt;<br />
&lt;/updateservers&gt;<br />
&lt;/source&gt;<br />
<br />
Update servers can be defined in the &lt;code&gt;&lt;updateservers&gt;&lt;/code&gt; element, a child of the root. This element may contain one or more &lt;code&gt;&lt;server&gt;&lt;/code&gt; element, each describing a location to fetch updates from. Each &lt;code&gt;&lt;server&gt;&lt;/code&gt; item can define the following attributes:<br />
<br />
{| class=&quot;wikitable&quot;<br />
! style=&quot;width: 150px&quot; | Attribute || style=&quot;width: 150px&quot; | Values || Description<br />
|-<br />
| type || &lt;code&gt;extension&lt;/code&gt;&lt;br /&gt;&lt;code&gt;collection&lt;/code&gt; || The update server type<br />
|-<br />
| priority || ''integer'' || The priority of the update server<br />
|-<br />
| name || ''string'' || The name of the update server<br />
|}<br />
<br />
More info:<br />
* [[J2.5:Developing a MVC Component/Adding an update server|Building a Joomla! Extension - Adding an update server]]<br />
* [[J2.5:Managing Component Updates|Managing Component Updates in Joomla 2.5]]<br />
<br />
== Examples ==<br />
For a real-life example, see [https://github.com/joomla/joomla-cms/blob/2.5.x/administrator/components/com_banners/banners.xml the manifest of the Banner component in the latest version of Joomla! 2.5].<br />
<br />
The Joomla testing process uses several extensions to test whether the installer works correctly. The latest versions of the manifests of these extensions are:<br />
<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/com_alpha/alpha.xml com_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/mod_alpha/mod_alpha.xml mod_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/plg_system_alpha/alpha.xml plg_system_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/tpl_simple/templateDetails.xml tpl_simple manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/lng_xx-XX/xx-XX.xml lng_xx-XX manifest]<br />
<br />
== Contributors ==<br />
*[[User:akede|Alex Kempkens]]<br />
*[[User:dperaza|Daniel Peraza]]<br />
*[[User:nikosdion|Nicholas K. Dionysopoulos]]<br />
*[[User:mrs.siam|Prasit Gebsaap]]<br />
*[[User:cppl|Craig Phillips]]<br />
<br />
<br />
[[Category:Extension development]]<br />
[[Category:Specifications]]</div>Mvangeest//docs.joomla.org/Framework:HomeFramework:Home2013-06-15T15:54:48Z<p>Mvangeest: /* What is the Joomla Framework ? */ Fixed links</p>
<hr />
<div>{{:{{FULLPAGENAME}}/header}}__NOTOC__<br />
&lt;div style=&quot;width:auto; vertical-align:top; background-color:#fff; margin:5px 0 10px 0; padding:8px; box-shadow: 1px 1px 8px #000;&quot;&gt;<br />
&lt;div style=&quot;float:right; padding-left:15px;&quot;&gt;&lt;markdown&gt;<br />
[![Build Status](https://travis-ci.org/joomla/joomla-framework.png?branch=master)](https://travis-ci.org/joomla/joomla-framework)<br />
&lt;/markdown&gt;&lt;/div&gt;<br />
== What is the Joomla Framework ? ==<br />
<br />
The &lt;code&gt;Joomla Framework&lt;/code&gt; is a platform for writing web and command line applications in PHP. It is free and open source software, distributed under the GNU General Public License version 2 or later.<br />
<br />
It is comprises code originally developed for the Joomla Content Management System (CMS). For more information about the Joomla CMS visit http://www.joomla.org/about-joomla.html.<br />
<br />
For news and information about developering with Joomla, please visit http://developer.joomla.org.<br />
<br />
View the Joomla Framework API Documentation at http://joomla.github.io/joomla-framework. Powered by [http://www.phpdoc.org phpDocumentor 2].<br />
<br />
You can discuss Joomla Framework development by joining the mailing list at http://groups.google.com/group/joomla-dev-framework.<br />
<br />
== Requirements ==<br />
<br />
* PHP 5.3.10<br />
<br />
== Installation ==<br />
=== Via Composer ===<br />
<br />
* Create a project and add a &lt;code&gt;composer.json&lt;/code&gt; file to it with the content :<br />
<br />
&lt;pre class=&quot;json&quot;&gt;{<br />
&quot;require&quot;: {<br />
&quot;joomla/joomla-framework&quot;: &quot;dev-master&quot;<br />
}<br />
}&lt;/pre&gt;<br />
* Download Composer<br />
<br />
&lt;code&gt;curl -sS &lt;nowiki&gt;https://getcomposer.org/installer&lt;/nowiki&gt; | php&lt;/code&gt;<br />
<br />
* Install the Joomla Framework<br />
<br />
&lt;code&gt;php composer.phar install&lt;/code&gt;<br />
<br />
=== Via Git ===<br />
<br />
&lt;code&gt;&lt;nowiki&gt;git clone git://github.com/joomla/joomla-framework.git&lt;/nowiki&gt;&lt;/code&gt;<br />
<br />
== Documentation ==<br />
<br />
General documentation about the Joomla Platform can be found under the [https://github.com/joomla/joomla-framework/tree/master/docs /docs] folder of the Git repository. In addition, each package has documentation in a &lt;code&gt;README.md&lt;/code&gt; file.<br />
<br />
== Reporting Bugs and Issue ==<br />
<br />
Bugs and issues found in the Joomla Framework code can be reported on the [https://github.com/joomla/joomla-framework/issues Issues] list.<br />
<br />
== Contributing ==<br />
<br />
All kind of contributions are welcome. Please read about how to contribute [https://github.com/joomla/joomla-framework/blob/master/CONTRIBUTING.markdown here].<br />
<br />
You may find tasks you can do on the [https://github.com/joomla/joomla-framework/issues Issues] list by filtering on labels and milestones<br />
&lt;/div&gt;<br />
[[Category:Joomla! Framework]]</div>Mvangeest//docs.joomla.org/Chunk:PlatformChunk:Platform2013-06-14T23:37:13Z<p>Mvangeest: Cleaned up</p>
<hr />
<div>&lt;noinclude&gt;{{chunk}}&lt;/noinclude&gt;__NOTOC__<br />
&lt;blockquote style=&quot;width:auto; border:1px solid grey; background-color:cornsilk; padding:5px; font-style:italic;&quot;&gt;The Joomla Platform is a platform for writing Web and command line applications in PHP. It is free and open source software, distributed under the GNU General Public License version 2 or later. The Joomla Content Management System (CMS) is built on top of the Joomla Platform.&lt;ref&gt;https://github.com/joomla/joomla-platform&lt;/ref&gt;&lt;/blockquote&gt;<br />
<br />
[[File:Architecture Joomla Platform.png|frame|400px|The Joomla! Platform]]<br />
<br />
As of 24 April 2013, the Platform project has been retired. The Platform has been merged back into the [[CMS]], and the [[Framework]] has taken its place as the standalone application framework for Joomla! applications.&lt;ref&gt;[https://github.com/joomla/joomla-platform/blob/84014ad35b0d6294a43fcd2745aecb130849ed9e/CONTRIBUTING.markdown CONTRIBUTING.markdown]&lt;/ref&gt;&lt;ref&gt;https://groups.google.com/d/msg/joomla-dev-platform/zzNrsCUKCts/hsBntnONm9MJ&lt;/ref&gt;<br />
<br />
The release of the Joomla Platform on 5 July 2011&lt;ref&gt;http://developer.joomla.org/code/cms/history/2010/12/02.html&lt;/ref&gt; marked an important change in the Joomla! CMS architecture. The Joomla! CMS was initially a monolithic application. One of the aims of the Joomla! project was to separate the codebase into the CMS and an underlying library, which could then be reused for other projects. In version 1.5 and 1.6, that separation was prepared by creating a division between the [[Framework (CMS 1.5 and 1.6)]] ''(which is unrelated to the new [[Framework]] project)'' and the Joomla! [[CMS]] Application. The Joomla! Platform project continued this effort by separating that framework into an independent project (both in terms of code and organization). The Joomla! Platform is an independent set of libraries which do not depend on the Joomla! CMS Application. These libraries are made up of libraries maintained by the Joomla! Project and libraries maintained by other 3rd party developers. The Platform could be used for web and command-line applications entirely independent of and unrelated to the CMS.<br />
<br />
The home of the Joomla! Platform was [https://github.com/joomla/joomla-platform the ''joomla/joomla-platform'' GitHub repository] that contains the source and documentation. The Platform stopped accepting contributions on or before 24 April 2013.<br />
&lt;noinclude&gt;&lt;references/&gt;&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Framework_(CMS_1.5_and_1.6)Framework (CMS 1.5 and 1.6)2013-06-14T16:46:38Z<p>Mvangeest: Adjusted link after page move</p>
<hr />
<div>{{Chunk:Framework quote}}<br />
{{Chunk:Framework (CMS 1.5 and 1.6)}}<br />
== API Reference ==<br />
<br />
On this page we'd like to provide you a way to reference of all classes and respective methods. Use the links below to navigate to further information about framework versions or the version classes which include, where possible, examples of use.<br />
<br />
If you would like to help us improve this resource, please read about the [[API Reference Project]].<br />
<br />
{{Navbox<br />
|state=off<br />
|navbar=off<br />
|title=API documentation is available in the following '''Joomla! Framework Versions'''<br />
|titlestyle=font-weight:normal; padding:5px;<br />
|image=[[File:Joomla vert logo.png|120px]]<br />
|group1= Select a framework version<br />
|group2= See also<br />
|group1style=font-size:1.1em; width:18%;<br />
|list1=<br />
* [[API15:Framework|Framework]] {{JVer|1.5}}<br />
* [[API16:Framework|Framework]] {{JVer|1.6}}<br />
|list2=<br />
* [[API17:Platform|Platform]] {{JVer|11.1}}<br />
|list1style=padding-left:10px; font-size:1.2em;<br />
|list2style=padding-left:10px; font-size:1.2em;<br />
}}<br />
<br />
=== See Also ===<br />
&lt;references/&gt;<br />
=== Further Reading ===<br />
*[[Joomla! Framework vs Joomla! Platform]]<br />
&lt;noinclude&gt;[[Category:Framework]][[Category:Subpackages]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Joomla!_Framework_(CMS_1.5_and_1.6)_vs_Joomla!_PlatformJoomla! Framework (CMS 1.5 and 1.6) vs Joomla! Platform2013-06-14T16:28:07Z<p>Mvangeest: Updated contents</p>
<hr />
<div>{{notice|This page discusses the differences between the Framework in the 1.5 and 1.6 versions of the Joomla CMS and the now-retired Joomla Platform. For information about the Joomla Framework project, see [[Framework]].}}<br />
<br />
== Framework (CMS 1.5 and 1.6) ==<br />
{{Chunk:Framework (CMS 1.5 and 1.6)}}<br />
== Introduction to Platform ==<br />
{{Chunk:Platform}}<br />
== Differences ==<br />
The Joomla! Platform can now be used to build other CMS Applications or Web and command line Applications specific to a developer's needs such as eCommerce, Social Media, and other stand alone Applications. The Platform is stored on GitHub, which allows developers to easily fork the Platform code for their own purposes, and then if they want, integrate it into the main code branch. This will encourage more developers and even attract larger corporations to contribute to the Joomla! Platform who might not have done so before.&lt;ref&gt;http://magazine.joomla.org/issues/Issue-Dec-2011/item/616-Write-your-own-App-using-Joomla-Platform?tmpl=component&amp;print=1&lt;/ref&gt; <br />
<br />
Another good thing about the separation of the the Joomla! Platform it has a release schedule of every 3 months which allows for a faster integration of core features used by extension developers. The version number is determined by the the year of its release. For example, Joomla! Platform 11.1 was released in 2011 and 12.1 was released in 2012.&lt;ref&gt;http://magazine.joomla.org/issues/Issue-Dec-2011/item/616-Write-your-own-App-using-Joomla-Platform?tmpl=component&amp;print=1&lt;/ref&gt;<br />
== See also and References ==<br />
&lt;references/&gt;<br />
&lt;noinclude&gt;[[Category:Platform]][[Category:Framework]][[Category:Frameworks and Platforms]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Joomla!_Framework_(CMS_1.5_and_1.6)_vs_Joomla!_PlatformJoomla! Framework (CMS 1.5 and 1.6) vs Joomla! Platform2013-06-14T16:24:16Z<p>Mvangeest: Mvangeest moved page Joomla! Framework vs Joomla! Platform to Joomla! Framework (CMS 1.5 and 1.6) vs Joomla! Platform: The name Framework has been reused for the new Joomla Framework project</p>
<hr />
<div>{{review}}<br />
== Framework ==<br />
{{Chunk:Framework (CMS 1.5 and 1.6)}}<br />
== Introduction to Platform ==<br />
{{Chunk:Platform}}<br />
== Differences ==<br />
The Joomla! Platform can now be used to build other CMS Applications or Web and command line Applications specific to a developer's needs such as eCommerce, Social Media, and other stand alone Applications. The Platform is stored on GitHub, which allows developers to easily fork the Platform code for their own purposes, and then if they want, integrate it into the main code branch. This will encourage more developers and even attract larger corporations to contribute to the Joomla! Platform who might not have done so before.&lt;ref&gt;http://magazine.joomla.org/issues/Issue-Dec-2011/item/616-Write-your-own-App-using-Joomla-Platform?tmpl=component&amp;print=1&lt;/ref&gt; <br />
<br />
Another good thing about the separation of the the Joomla! Platform it has a release schedule of every 3 months which allows for a faster integration of core features used by extension developers. The version number is determined by the the year of its release. For example, Joomla! Platform 11.1 was released in 2011 and 12.1 was released in 2012.&lt;ref&gt;http://magazine.joomla.org/issues/Issue-Dec-2011/item/616-Write-your-own-App-using-Joomla-Platform?tmpl=component&amp;print=1&lt;/ref&gt;<br />
== See also and References ==<br />
&lt;references/&gt;<br />
&lt;noinclude&gt;[[Category:Platform]][[Category:Framework]][[Category:Frameworks and Platforms]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Joomla!_Framework_vs_Joomla!_PlatformJoomla! Framework vs Joomla! Platform2013-06-14T16:24:16Z<p>Mvangeest: Mvangeest moved page Joomla! Framework vs Joomla! Platform to Joomla! Framework (CMS 1.5 and 1.6) vs Joomla! Platform: The name Framework has been reused for the new Joomla Framework project</p>
<hr />
<div>#REDIRECT [[Joomla! Framework (CMS 1.5 and 1.6) vs Joomla! Platform]]</div>Mvangeest//docs.joomla.org/Chunk:FrameworkChunk:Framework2013-06-14T16:14:48Z<p>Mvangeest: Added link</p>
<hr />
<div>&lt;noinclude&gt;{{chunk}}&lt;/noinclude&gt;__NOTOC__<br />
The Joomla Framework is a platform for writing web and command line applications in PHP. It is free and open source software, distributed under the GNU General Public License version 2 or later.&lt;ref&gt;https://github.com/joomla/joomla-framework/&lt;/ref&gt;<br />
<br />
The Framework comprises code originally developed for the Joomla [[Content Management System]] and is a continuation of the [[Platform]] project. The Joomla Framework and the Joomla CMS are separate projects with separate development teams. Unlike the Platform, the Framework is not primarily intended as a platform for the Joomla CMS, and the Joomla CMS is not currently built on the Framework. More information about the differences between the Platform and the Framework can be found in [http://magazine.joomla.org/issues/issue-mar-2013/item/1136-differences-between-the-joomla-framework-and-joomla-platform the March 2013 edition of the Joomla Community Magazine].<br />
&lt;noinclude&gt;&lt;references/&gt;&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Chunk:PlatformChunk:Platform2013-06-14T15:36:53Z<p>Mvangeest: Fixed layout, hopefully</p>
<hr />
<div>&lt;noinclude&gt;{{chunk}}&lt;/noinclude&gt;__NOTOC__<br />
&lt;blockquote style=&quot;width:auto; border:1px solid grey; background-color:cornsilk; padding:5px; font-style:italic;&quot;&gt;The Joomla Platform is a platform for writing Web and command line applications in PHP. It is free and open source software, distributed under the GNU General Public License version 2 or later. The Joomla Content Management System (CMS) is built on top of the Joomla Platform.&lt;ref&gt;https://github.com/joomla/joomla-platform&lt;/ref&gt;&lt;/blockquote&gt;<br />
<br />
[[File:Architecture Joomla Platform.png|frame|400px|The Joomla! Platform]]<br />
<br />
As of 24 April 2013, the Platform project has been retired. The Platform has been merged back into the [[CMS]] (see also http://github.com/joomla/joomla-cms), and the [[Framework]] (see also http://github.com/joomla/joomla-framework) has taken its place as the standalone application framework for Joomla! applications.&lt;ref&gt;[https://github.com/joomla/joomla-platform/blob/84014ad35b0d6294a43fcd2745aecb130849ed9e/CONTRIBUTING.markdown CONTRIBUTING.markdown]&lt;/ref&gt;&lt;ref&gt;https://groups.google.com/d/msg/joomla-dev-platform/zzNrsCUKCts/hsBntnONm9MJ&lt;/ref&gt;<br />
<br />
The release of the Joomla Platform on 5 July 2011&lt;ref&gt;http://developer.joomla.org/code/cms/history/2010/12/02.html&lt;/ref&gt; marked an important change in the Joomla! CMS architecture. The Joomla! CMS was initially a monolithic application. One of the aims of the Joomla! project was to separate the codebase into the CMS and an underlying library, which could then be reused for other projects. In version 1.5 and 1.6, that separation was prepared by creating a division between the [[Framework (CMS 1.5 and 1.6)]] ''(which is unrelated to the new [[Framework]] project)'' and the Joomla! [[CMS]] Application. The Joomla! Platform project continued this effort by separating that framework into an independent project (both in terms of code and organization). The Joomla! Platform is an independent set of libraries which do not depend on the Joomla! CMS Application. These libraries are made up of libraries maintained by the Joomla! Project and libraries maintained by other 3rd party developers. The Platform could be used for web and command-line applications entirely independent of and unrelated to the CMS.<br />
<br />
The home of the Joomla! Platform was [https://github.com/joomla/joomla-platform the ''joomla/joomla-platform'' GitHub repository] that contains the source and documentation. The Platform stopped accepting contributions on or before 24 April 2013.<br />
&lt;noinclude&gt;&lt;references/&gt;&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Main_PageMain Page2013-06-14T15:33:30Z<p>Mvangeest: The Platform has been retired - updated references to the Framework</p>
<hr />
<div>__NOTOC__<br />
{| cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; style=&quot;margin:0em 0em 1em 0em; width:100%;&quot;<br />
| colspan=&quot;1&quot; style=&quot;width:100%; vertical-align:top; border:1px solid #B356C1; background-color:#fff; -moz-border-radius:10px; border-radius:10px;&quot; |<br />
&lt;div style=&quot;background-color:#fff; padding:0.8em 1.1em 0 1.1em; margin:0 7px;&quot;&gt;&lt;h1&gt;&lt;span class=&quot;mw-headline&quot;&gt;Joomla! Official Documentation&lt;/span&gt;&lt;/h1&gt;&lt;/div&gt;<br />
&lt;div style=&quot;padding:1em 1em 1em 1em;&quot;&gt; &lt;!--Note: Top, right, bottom, left --&gt;<br />
<br />
{| cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; style=&quot;margin:0em 0em 1em 0em; width:100%&quot;<br />
| style=&quot;width:50%; vertical-align:top; border:1px solid #abd5f5; background-color: #fff;-moz-border-radius:10px; border-radius:10px;&quot; rowspan=&quot;1&quot;|<br />
&lt;div style=&quot;border-bottom:1px solid abd5f5; background-color:#d0e5f5; padding:0.2em 0.5em 0.2em 0.5em; font-size:110%; font-weight:bold; -moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;Reader profiles&lt;/div&gt;<br />
&lt;div style=&quot;padding:0.4em 1em 0.3em 1em;&quot;&gt;<br />
&lt;!-- PICTURE ON LEFT OF TWO BOX SECTION --&gt;<br />
Find the profile that most accurately describes your role and you will find the documentation that you need more quickly. These are the most frequent profiles...<br />
* [[Beginners]]<br />
* [[Developers]]<br />
* [[Web designers]]<br />
* [[Administrators]]<br />
* [[Evaluators]]<br />
* [[Joomla! Code Contributors]]<br />
None of the above? Then look for [[Start here|more user profiles]].<br />
&lt;/div&gt;<br />
<br />
| style=&quot;padding:0em 0.5em 0em 0.5em;&quot; |<br />
<br />
| style=&quot;width:30%; vertical-align:top; background-color: #fff;-moz-border-radius:10px; border-radius:10px;&quot; rowspan=&quot;1&quot;|<br />
&lt;div style=&quot;border-bottom:1px solid abd5f5; background-color:#fff; padding:0.2em 0.5em 0.2em 0.5em; font-size:110%; font-weight:bold;-moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;Quick links&lt;/div&gt;<br />
&lt;div style=&quot;padding:0.4em 1em 0.3em 1em;&quot;&gt;<br />
&lt;!-- PICTURE ON LEFT OF TWO BOX SECTION --&gt;<br />
* [[:Category:FAQ|Frequently Asked Questions]]<br />
* [[:Category:Tips and tricks|Tips and tricks]]<br />
* [[Security Checklist|Joomla! Security Checklist]]<br />
* [[Vulnerable Extensions List]]<br />
* [[:Category:Top_Level|Browse all categories]]<br />
* [[JDOC:Wiki policy|Wiki policy]]<br />
* [[JEDL|Documentation license]]<br />
* [[Framework:Home|Joomla! Framework]]<br />
* [[Glossary]]<br />
* [[References]]<br />
&lt;/div&gt;<br />
<br />
| style=&quot;padding:0em 0.5em 0em 0.5em;&quot; |<br />
<br />
| style=&quot;vertical-align:top; border:none; background-color:#fff;&quot; |<br />
&lt;!-- PICTURE ON RIGHT OF TWO BOX SECTION--&gt;<br />
[[Image:documentation_all_together.jpg|border|right]]<br />
|}<br />
<br />
{| cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; style=&quot;margin:0em 0em 1em 0em; width:100%&quot;<br />
| style=&quot;width:50%; vertical-align:top; border:1px solid #abd5f5; background-color: #f1f5fc;-moz-border-radius:10px; border-radius:10px;&quot; rowspan=&quot;1&quot;|<br />
&lt;div style=&quot;border-bottom:1px solid abd5f5; background-color:#d0e5f5; padding:0.2em 0.5em 0.2em 0.5em; font-size:110%; font-weight:bold;-moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;Getting started&lt;/div&gt;<br />
&lt;div style=&quot;padding:0.4em 1em 0.3em 1em;&quot;&gt;<br />
&lt;!-- PICTURE ON LEFT OF TWO BOX SECTION --&gt;<br />
If you have only recently starting working with Joomla you will probably have experienced the pain of learning a new system. New terminology, new ways of doing things, perhaps even the web itself may be new to you. Then let these guides relieve some of that pain.<br />
<br />
* [[J3.1:Getting Started with Joomla!|Getting Started with Joomla! 3.x]] {{JVer|3.x}}<br />
* [[Getting Started with Joomla!|Getting Started with Joomla! 2.5]] {{JVer|2.5}}<br />
* [[J1.5:Getting Started with Joomla!|Getting Started with Joomla! 1.5]] {{JVer|1.5}}<br />
&lt;/div&gt;<br />
<br />
| style=&quot;padding:0em 0.5em 0em 0.5em;&quot; |<br />
<br />
| style=&quot;width:50%; vertical-align:top; border:1px solid Gold; background-color: LightYellow;-moz-border-radius:10px; border-radius:10px;&quot; |<br />
&lt;div style=&quot;border-bottom:1px solid #Gold; background-color:#ffffaa; padding:0.2em 0.5em 0.2em 0.5em; font-size:110%; font-weight:bold;-moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;Important&lt;/div&gt;<br />
&lt;div style=&quot;padding:0.4em 1em 0.3em 1em;&quot;&gt;<br />
&lt;!-- PICTURE ON RIGHT OF TWO BOX SECTION--&gt;<br />
'''You don't need to register here if you just want to read the documentation.'''<br />
<br />
You should only register if you want to make changes to the information contained here. Also note that registration on this wiki is entirely separate from registration on our other sites, such as the [http://forum.joomla.org forum].<br />
&lt;/div&gt;<br />
|}<br />
<br />
&lt;/div&gt;<br />
|}<br />
<br />
{| cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; style=&quot;margin:0em 0em 1em 0em; width:100%&quot;<br />
| style=&quot;width:50%; vertical-align:top; border:1px solid #abd5f5; background-color: #f1f5fc;-moz-border-radius:10px; border-radius:10px;&quot; rowspan=&quot;1&quot;|<br />
&lt;div style=&quot;border-bottom:1px solid abd5f5; background-color:#d0e5f5; padding:0.2em 0.5em 0.2em 0.5em; font-size:110%; font-weight:bold;-moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;Coming soon&lt;/div&gt;<br />
&lt;div style=&quot;padding:0.4em 1em 0.3em 1em;&quot;&gt;<br />
&lt;!-- PICTURE ON LEFT OF TWO BOX SECTION --&gt;<br />
With Joomla 2.5 safely released the focus of development is shifting to 3. Joomla 3.1 was released in April 2013. This is the second of a new series (3.0/3.1/3.2/3.5) and maintaining backwards compatibility with 2.5 will not be required.<br />
<br />
* [[:Category:Version 3.1 FAQ|Version 3.1 FAQs]]<br />
&lt;/div&gt;<br />
<br />
| style=&quot;padding:0em 0.5em 0em 0.5em;&quot; |<br />
<br />
| style=&quot;width:50%; vertical-align:top; border:1px solid Gold; background-color: LightYellow;-moz-border-radius:10px; border-radius:10px;&quot; |<br />
&lt;div style=&quot;border-bottom:1px solid #Gold; background-color:#ffffaa; padding:0.2em 0.5em 0.2em 0.5em; font-size:110%; font-weight:bold;-moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;Joomla [[Framework]]&lt;/div&gt;<br />
&lt;div style=&quot;padding:0.4em 1em 0.3em 1em;&quot;&gt;<br />
&lt;!-- PICTURE ON RIGHT OF TWO BOX SECTION--&gt;<br />
The Joomla Framework, a modern PHP application platform project independent of the CMS, is available.<br />
<br />
* [https://github.com/joomla/joomla-framework Joomla Framework on Github]<br />
* [http://joomla.github.io/joomla-framework/ API documentation]<br />
* [[Platform|The Platform, predecessor of the Framework]]<br />
&lt;/div&gt;<br />
|}<br />
<br />
{| cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; style=&quot;margin:0em 0em 1em 0em; width:100%&quot;<br />
| style=&quot;width:50%; vertical-align:top; border:1px solid #abd5f5; background-color: #f1f5fc;-moz-border-radius:10px; border-radius:10px;&quot; rowspan=&quot;1&quot;|<br />
&lt;div style=&quot;border-bottom:1px solid abd5f5; background-color:#d0e5f5; padding:0.2em 0.5em 0.2em 0.5em; font-size:110%; font-weight:bold;-moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;Quick links for [[Administrators]]&lt;/div&gt;<br />
&lt;div style=&quot;padding:0.4em 1em 0.3em 1em;&quot;&gt;<br />
&lt;!-- PICTURE ON LEFT OF TWO BOX SECTION --&gt;<br />
* [[Joomla Installation|Installation]]<br />
* [[Template Management]]<br />
* [[Article Management]]<br />
* [[User Management|User and Access Management]]<br />
* [[Menu Management]]<br />
* [[Security]]<br />
* [[Module Management]]<br />
* [[Component Management]]<br />
* [[Category Management]]<br />
* [[Plugin Management]]<br />
* [[Global Configuration Management]]<br />
&lt;/div&gt;<br />
<br />
| style=&quot;padding:0em 0.5em 0em 0.5em;&quot; |<br />
<br />
| style=&quot;width:50%; vertical-align:top; border:1px solid Gold; background-color: LightYellow;-moz-border-radius:10px; border-radius:10px;&quot; |<br />
&lt;div style=&quot;border-bottom:1px solid #Gold; background-color:#ffffaa; padding:0.2em 0.5em 0.2em 0.5em; font-size:110%; font-weight:bold;-moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;{{JVer|{{CurrentLTSVer|minor}}}} Joomla! {{CurrentLTSVer|minor}}&lt;/div&gt;<br />
&lt;div style=&quot;padding:0.4em 1em 0.3em 1em;&quot;&gt;<br />
&lt;!-- PICTURE ON RIGHT OF TWO BOX SECTION--&gt;<br />
Joomla! {{CurrentLTSVer|minor}} is the current [[Release and support cycle|LTS version]]. The previous LTS version, Joomla 1.5, is still widely used and will be supported with security fixes only until September 2012.<br />
* [[J2.5:Upgrading_from_an_existing_version|Upgrading your site from 1.6/1.7 to 2.5]]<br />
* [[J2.5:Migrating_from_Joomla_1.5_to_Joomla_2.5|Migrating your site from 1.5 to 2.5]]<br />
* [[:Category:Version {{CurrentLTSVer}} FAQ|Version {{CurrentLTSVer}} FAQ]]<br />
* [http://www.joomla.org/about-joomla/technical-requirements.html Technical Requirements]<br />
* [[Installing Joomla!]]<br />
<br />
For more information see the [[:Category:Joomla! {{CurrentLTSVer|minor}}|Joomla {{CurrentLTSVer|minor}} category page]].<br />
&lt;/div&gt;<br />
|}<br />
<br />
{| cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; style=&quot;margin:0em 0em 1em 0em; width:100%&quot;<br />
| style=&quot;width:50%; vertical-align:top; border:1px solid #abd5f5; background-color: #f1f5fc;-moz-border-radius:10px; border-radius:10px;&quot; rowspan=&quot;1&quot;|<br />
&lt;div style=&quot;border-bottom:1px solid abd5f5; background-color:#d0e5f5; padding:0.2em 0.5em 0.2em 0.5em; font-size:110%; font-weight:bold;-moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;Quick links for [[Developers]]&lt;/div&gt;<br />
&lt;div style=&quot;padding:0.4em 1em 0.3em 1em;&quot;&gt;<br />
&lt;!-- PICTURE ON LEFT OF TWO BOX SECTION --&gt;<br />
* [http://api.joomla.org/ Platform API Documentation]<br />
* [[Template Development|Templates]]<br />
* [[Component Development|Components]]<br />
* [[Module Development|Modules]]<br />
* [[Language Development|Languages]]<br />
* [[Plugin Development|Plugins]]<br />
* [[CMS]] versus [[Platform]]<br />
* [http://developer.joomla.org Joomla! Developer Portal]<br />
* [[Portal:Bug_Squad|Joomal! Bug Squad members]]<br />
&lt;/div&gt;<br />
<br />
| style=&quot;padding:0em 0.5em 0em 0.5em;&quot; |<br />
<br />
| style=&quot;width:50%; vertical-align:top; border:1px solid Gold; background-color: LightYellow;-moz-border-radius:10px; border-radius:10px;&quot; |<br />
&lt;div style=&quot;border-bottom:1px solid #Gold; background-color:#ffffaa; padding:0.2em 0.5em 0.2em 0.5em; font-size:110%; font-weight:bold;-moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;{{JVer|{{CurrentSTSVer|minor}}}} Joomla! {{CurrentSTSVer|minor}}&lt;/div&gt;<br />
&lt;div style=&quot;padding:0.4em 1em 0.3em 1em;&quot;&gt;<br />
&lt;!-- PICTURE ON RIGHT OF TWO BOX SECTION--&gt;<br />
Joomla {{CurrentSTSVer|minor}} is the latest [[Release and support cycle|STS version]] after Joomla 2.5. Support for Joomla {{CurrentSTSVer|minor}} is still active.<br />
* [[Technical requirements]]<br />
* [[J{{CurrentSTSVer|minor}}:Installing Joomla!|Installing Joomla! {{CurrentSTSVer|major}}]]<br />
* [[J{{CurrentSTSVer|minor}}:What's new in Joomla!|What's new]]<br />
* [[J{{CurrentSTSVer|minor}}:Access_Control_List_Tutorial|Access control system]]<br />
&lt;!-- * [[International Enhancements for Version {{CurrentSTSVer|minor}}|International enhancements]] --&gt;<br />
&lt;!-- * [[Layout Overrides in Joomla! {{CurrentSTSVer|minor}}|Layout overrides]] --&gt;<br />
* [[:Category:Version {{CurrentSTSVer}} FAQ|Version {{CurrentSTSVer}} FAQ]]<br />
<br />
For more information see the [[:Category:Joomla! {{CurrentSTSVer|minor}}|Joomla {{CurrentSTSVer|minor}} category page]].<br />
&lt;/div&gt;<br />
|}<br />
<br />
{| cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; style=&quot;margin:0em 0em 1em 0em; width:100%&quot;<br />
| colspan=&quot;1&quot; style=&quot;width:100%; vertical-align:top; border:1px solid Sienna; background-color:Cornsilk;-moz-border-radius:10px; border-radius:10px;&quot; |<br />
&lt;div style=&quot;border-bottom:1px solid Sienna; background-color:Wheat; padding:0.2em 0.5em 0.2em 0.5em; font-size:130%; font-weight:bold;-moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;Helping with the documentation effort&lt;/div&gt;<br />
&lt;div style=&quot;padding:1em 1em 1em 1em;&quot;&gt; &lt;!--Note: Top, right, bottom, left --&gt;<br />
<br />
{| cellspacing=&quot;0&quot; cellpadding=&quot;0&quot; style=&quot;margin:0em 0em 1em 0em; width:100%&quot;<br />
| style=&quot;width:50%; vertical-align:top; border:1px solid #abd5f5; background-color: #f1f5fc;-moz-border-radius:10px; border-radius:10px;&quot; rowspan=&quot;1&quot;|<br />
&lt;div style=&quot;border-bottom:1px solid abd5f5; background-color:#d0e5f5; padding:0.2em 0.5em 0.2em 0.5em; font-size:110%; font-weight:bold;-moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;Documentation Projects&lt;/div&gt;<br />
&lt;div style=&quot;padding:0.4em 1em 0.3em 1em;&quot;&gt;<br />
&lt;!-- PICTURE ON LEFT OF TWO BOX SECTION --&gt;<br />
You don't need to join the [[Documentation Working Group]] to help us improve the documentation. Just [[Special:UserLogin|register]] on this wiki and get started. Feel free to fix any errors you find; take a look in the [[JDOC:Cookie jar|Cookie jar]]; or consider helping out in one of our mini-projects...<br />
<br />
{{:JDOC:Projects}}<br />
&lt;/div&gt;<br />
<br />
| style=&quot;padding:0em 0.5em 0em 0.5em;background-color:CornSilk;&quot; |<br />
<br />
| style=&quot;width:50%; vertical-align:top; border:1px solid Gold; background-color: White;-moz-border-radius:10px; border-radius:10px;&quot; |<br />
&lt;div style=&quot;border-bottom:1px solid #Gold; background-color:#ffffaa; padding:0.2em 0.5em 0.2em 0.5em; font-size:110%; font-weight:bold;-moz-border-radius:10px 10px 0 0; border-radius:10px 10px 0 0;&quot;&gt;Most popular pages&lt;/div&gt;<br />
&lt;div style=&quot;padding:0.4em 1em 0.3em 1em;&quot;&gt;<br />
&lt;!-- PICTURE ON RIGHT OF TWO BOX SECTION--&gt;<br />
{{Most popular pages}}<br />
&lt;/div&gt;<br />
|}<br />
<br />
&lt;/div&gt;<br />
|}<br />
{{license}}</div>Mvangeest//docs.joomla.org/Chunk:PlatformChunk:Platform2013-06-14T15:24:07Z<p>Mvangeest: Updated contents, adjusted layout</p>
<hr />
<div>&lt;noinclude&gt;{{chunk}}&lt;/noinclude&gt;__NOTOC__<br />
&lt;blockquote style=&quot;width:auto; border:1px solid grey; background-color:cornsilk; padding:5px; font-style:italic;&quot;&gt;The Joomla Platform is a platform for writing Web and command line applications in PHP. It is free and open source software, distributed under the GNU General Public License version 2 or later. The Joomla Content Management System (CMS) is built on top of the Joomla Platform.&lt;ref&gt;https://github.com/joomla/joomla-platform&lt;/ref&gt;&lt;/blockquote&gt;<br />
<br />
[[File:Architecture Joomla Platform.png|frame|400px|The Joomla! Platform]]<br />
<br />
As of 24 April 2013, the Platform project has been retired. The Platform has been merged back into the [[CMS]] (see also http://github.com/joomla/joomla-cms), and the [[Framework]] (see also http://github.com/joomla/joomla-framework) has taken its place as the standalone application framework for Joomla! applications.&lt;ref&gt;[https://github.com/joomla/joomla-platform/blob/84014ad35b0d6294a43fcd2745aecb130849ed9e/CONTRIBUTING.markdown CONTRIBUTING.markdown]&lt;/ref&gt;&lt;ref&gt;https://groups.google.com/d/msg/joomla-dev-platform/zzNrsCUKCts/hsBntnONm9MJ&lt;/ref&gt;<br />
<br />
The release of the Joomla Platform on 5 July 2011&lt;ref&gt;http://developer.joomla.org/code/cms/history/2010/12/02.html&lt;/ref&gt; marked an important change in the Joomla! CMS architecture. The Joomla! CMS was initially a monolithic application. One of the aims of the Joomla! project was to separate the codebase into the CMS and an underlying library, which could then be reused for other projects. In version 1.5 and 1.6, that separation was prepared by creating a division between the [[Framework (CMS 1.5 and 1.6)]] ''(which is unrelated to the new [[Framework]] project)'' and the Joomla! [[CMS]] Application. The Joomla! Platform project continued this effort by separating that framework into an independent project (both in terms of code and organization). The Joomla! Platform is an independent set of libraries which do not depend on the Joomla! CMS Application. These libraries are made up of libraries maintained by the Joomla! Project and libraries maintained by other 3rd party developers. The Platform could be used for web and command-line applications entirely independent of and unrelated to the CMS.<br />
<br />
The home of the Joomla! Platform was [https://github.com/joomla/joomla-platform the ''joomla/joomla-platform'' GitHub repository] that contains the source and documentation. The Platform stopped accepting contributions on or before 24 April 2013.<br />
<br />
&lt;noinclude&gt;&lt;references/&gt;&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/FrameworkFramework2013-06-14T14:39:42Z<p>Mvangeest: Started page about the Framework project</p>
<hr />
<div>{{Chunk:Framework}}<br />
The home of the Joomla! Framework is [https://github.com/joomla/joomla-framework/ the joomla/joomla-framework GitHub repository] that contains the source, documentation and means to contribute (pull requests).<br />
<br />
API documentation for the Framework can be found on http://joomla.github.io/joomla-framework/.<br />
<br />
Framework development can be discussed on [http://groups.google.com/group/joomla-dev-framework the joomla-dev-framework Google Group].<br />
<br />
== References ==<br />
&lt;references/&gt;</div>Mvangeest//docs.joomla.org/Chunk:FrameworkChunk:Framework2013-06-14T14:32:21Z<p>Mvangeest: Started page about the Framework project</p>
<hr />
<div>&lt;noinclude&gt;{{chunk}}&lt;/noinclude&gt;__NOTOC__<br />
The Joomla Framework is a platform for writing web and command line applications in PHP. It is free and open source software, distributed under the GNU General Public License version 2 or later.&lt;ref&gt;https://github.com/joomla/joomla-framework/&lt;/ref&gt;<br />
<br />
The Framework comprises code originally developed for the Joomla [[Content Management System]] and is a continuation of the [[Platform]] project. The Joomla Framework and the Joomla CMS are separate projects with separate development teams. Unlike the Platform, the Framework is not primarily intended as a platform for the Joomla CMS, and the Joomla CMS is not currently built on the Framework.<br />
&lt;noinclude&gt;&lt;references/&gt;&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Talk:Framework_(CMS_1.5_and_1.6)Talk:Framework (CMS 1.5 and 1.6)2013-06-14T14:20:36Z<p>Mvangeest: Mvangeest moved page Talk:Framework to Talk:Framework (CMS 1.5 and 1.6): The name Framework has been reused for the new Joomla Framework project</p>
<hr />
<div>== Wanted pages on the Framework ==<br />
<br />
While emptying the Tutorial namespace, I deleted the Tutorial:Framework page. It only contained a sentence praising the exquisite flexibility of the &quot;new, streamlined&quot; framework, plus the following two links:<br />
* [[framework:database_part1|Using the 1.5 Database Libraries]]<br />
* [[framework:router_part1|Creating Custom URLs]]<br />
These pages were probably requested by developers, so if anyone has the time to write them, please do.<br />
[[User:Mvangeest|Mvangeest]] 18:29, 14 January 2011 (UTC)</div>Mvangeest//docs.joomla.org/FrameworkFramework2013-06-14T14:20:35Z<p>Mvangeest: Mvangeest moved page Framework to Framework (CMS 1.5 and 1.6): The name Framework has been reused for the new Joomla Framework project</p>
<hr />
<div>#REDIRECT [[Framework (CMS 1.5 and 1.6)]]</div>Mvangeest//docs.joomla.org/Framework_(CMS_1.5_and_1.6)Framework (CMS 1.5 and 1.6)2013-06-14T14:20:34Z<p>Mvangeest: Mvangeest moved page Framework to Framework (CMS 1.5 and 1.6): The name Framework has been reused for the new Joomla Framework project</p>
<hr />
<div>{{Chunk:Framework quote}}<br />
{{Chunk:Framework}}<br />
== API Reference ==<br />
<br />
On this page we'd like to provide you a way to reference of all classes and respective methods. Use the links below to navigate to further information about framework versions or the version classes which include, where possible, examples of use.<br />
<br />
If you would like to help us improve this resource, please read about the [[API Reference Project]].<br />
<br />
{{Navbox<br />
|state=off<br />
|navbar=off<br />
|title=API documentation is available in the following '''Joomla! Framework Versions'''<br />
|titlestyle=font-weight:normal; padding:5px;<br />
|image=[[File:Joomla vert logo.png|120px]]<br />
|group1= Select a framework version<br />
|group2= See also<br />
|group1style=font-size:1.1em; width:18%;<br />
|list1=<br />
* [[API15:Framework|Framework]] {{JVer|1.5}}<br />
* [[API16:Framework|Framework]] {{JVer|1.6}}<br />
|list2=<br />
* [[API17:Platform|Platform]] {{JVer|11.1}}<br />
|list1style=padding-left:10px; font-size:1.2em;<br />
|list2style=padding-left:10px; font-size:1.2em;<br />
}}<br />
<br />
=== See Also ===<br />
&lt;references/&gt;<br />
=== Further Reading ===<br />
*[[Joomla! Framework vs Joomla! Platform]]<br />
&lt;noinclude&gt;[[Category:Framework]][[Category:Subpackages]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/API16:FrameworkAPI16:Framework2013-06-14T14:18:43Z<p>Mvangeest: Archive maintenance: a page move could have caused major confusion</p>
<hr />
<div>{{Chunk:Framework (CMS 1.5 and 1.6)}}<br />
<br />
{| class=&quot;wikitable&quot;<br />
|-<br />
|-<br />
|[[API16:JAccess|JAccess]]<br />
|[[API16:JElementComponentLayouts|JElementComponentLayouts]]<br />
|[[API16:JFormFieldSQL|JFormFieldSQL]]<br />
|[[API16:JPane|JPane]]<br />
|-<br />
|[[API16:JAdapter|JAdapter]]<br />
|[[API16:JElementContentLanguages|JElementContentLanguages]]<br />
|[[API16:JFormFieldSessionHandler|JFormFieldSessionHandler]]<br />
|[[API16:JPaneSliders|JPaneSliders]]<br />
|-<br />
|[[API16:JAdapterInstance|JAdapterInstance]]<br />
|[[API16:JElementEditors|JElementEditors]]<br />
|[[API16:JFormFieldSpacer|JFormFieldSpacer]]<br />
|[[API16:JPaneTabs|JPaneTabs]]<br />
|-<br />
|[[API16:JApplication|JApplication]]<br />
|[[API16:JElementFilelist|JElementFilelist]]<br />
|[[API16:JFormFieldTemplateStyle|JFormFieldTemplateStyle]]<br />
|[[API16:JParameter|JParameter]]<br />
|-<br />
|[[API16:JApplicationHelper|JApplicationHelper]]<br />
|[[API16:JElementFolderlist|JElementFolderlist]]<br />
|[[API16:JFormFieldText|JFormFieldText]]<br />
|[[API16:JPath|JPath]]<br />
|-<br />
|[[API16:JArchive|JArchive]]<br />
|[[API16:JElementHelpsites|JElementHelpsites]]<br />
|[[API16:JFormFieldTextarea|JFormFieldTextarea]]<br />
|[[API16:JPathway|JPathway]]<br />
|-<br />
|[[API16:JArchiveBzip2|JArchiveBzip2]]<br />
|[[API16:JElementHidden|JElementHidden]]<br />
|[[API16:JFormFieldTimezone|JFormFieldTimezone]]<br />
|[[API16:JPlugin|JPlugin]]<br />
|-<br />
|[[API16:JArchiveGzip|JArchiveGzip]]<br />
|[[API16:JElementImageList|JElementImageList]]<br />
|[[API16:JFormFieldUser|JFormFieldUser]]<br />
|[[API16:JPluginHelper|JPluginHelper]]<br />
|-<br />
|[[API16:JArchiveTar|JArchiveTar]]<br />
|[[API16:JElementLanguages|JElementLanguages]]<br />
|[[API16:JFormFieldUserGroup|JFormFieldUserGroup]]<br />
|[[API16:JProfiler|JProfiler]]<br />
|-<br />
|[[API16:JArchiveZip|JArchiveZip]]<br />
|[[API16:JElementList|JElementList]]<br />
|[[API16:JFormRule|JFormRule]]<br />
|[[API16:JRegistry|JRegistry]]<br />
|-<br />
|[[API16:JArrayHelper|JArrayHelper]]<br />
|[[API16:JElementMenu|JElementMenu]]<br />
|[[API16:JFormRuleBoolean|JFormRuleBoolean]]<br />
|[[API16:JRegistryFormat|JRegistryFormat]]<br />
|-<br />
|[[API16:JAuthentication|JAuthentication]]<br />
|[[API16:JElementMenuItem|JElementMenuItem]]<br />
|[[API16:JFormRuleEmail|JFormRuleEmail]]<br />
|[[API16:JRegistryFormatINI|JRegistryFormatINI]]<br />
|-<br />
|[[API16:JAuthenticationResponse|JAuthenticationResponse]]<br />
|[[API16:JElementModuleLayouts|JElementModuleLayouts]]<br />
|[[API16:JFormRuleEquals|JFormRuleEquals]]<br />
|[[API16:JRegistryFormatJSON|JRegistryFormatJSON]]<br />
|-<br />
|[[API16:JBrowser|JBrowser]]<br />
|[[API16:JElementPassword|JElementPassword]]<br />
|[[API16:JFormRuleRules|JFormRuleRules]]<br />
|[[API16:JRegistryFormatPHP|JRegistryFormatPHP]]<br />
|-<br />
|[[API16:JBuffer|JBuffer]]<br />
|[[API16:JElementRadio|JElementRadio]]<br />
|[[API16:JFormRuleUsername|JFormRuleUsername]]<br />
|[[API16:JRegistryFormatXML|JRegistryFormatXML]]<br />
|-<br />
|[[API16:JButton|JButton]]<br />
|[[API16:JElementSQL|JElementSQL]]<br />
|[[API16:JFormValidator|JFormValidator]]<br />
|[[API16:JRequest|JRequest]]<br />
|-<br />
|[[API16:JButtonConfirm|JButtonConfirm]]<br />
|[[API16:JElementSpacer|JElementSpacer]]<br />
|[[API16:JFrameworkConfig|JFrameworkConfig]]<br />
|[[API16:JResponse|JResponse]]<br />
|-<br />
|[[API16:JButtonCustom|JButtonCustom]]<br />
|[[API16:JElementTemplateStyle|JElementTemplateStyle]]<br />
|[[API16:JHelp|JHelp]]<br />
|[[API16:JRoute|JRoute]]<br />
|-<br />
|[[API16:JButtonHelp|JButtonHelp]]<br />
|[[API16:JElementText|JElementText]]<br />
|[[API16:JHtml|JHtml]]<br />
|[[API16:JRouter|JRouter]]<br />
|-<br />
|[[API16:JButtonLink|JButtonLink]]<br />
|[[API16:JElementTextarea|JElementTextarea]]<br />
|[[API16:JHtmlAccess|JHtmlAccess]]<br />
|[[API16:JRule|JRule]]<br />
|-<br />
|[[API16:JButtonPopup|JButtonPopup]]<br />
|[[API16:JElementTimezones|JElementTimezones]]<br />
|[[API16:JHtmlBehavior|JHtmlBehavior]]<br />
|[[API16:JRules|JRules]]<br />
|-<br />
|[[API16:JButtonSeparator|JButtonSeparator]]<br />
|[[API16:JElementUserGroup|JElementUserGroup]]<br />
|[[API16:JHtmlCategory|JHtmlCategory]]<br />
|[[API16:JSession|JSession]]<br />
|-<br />
|[[API16:JButtonStandard|JButtonStandard]]<br />
|[[API16:JError|JError]]<br />
|[[API16:JHtmlContent|JHtmlContent]]<br />
|[[API16:JSessionStorage|JSessionStorage]]<br />
|-<br />
|[[API16:JCache|JCache]]<br />
|[[API16:JEvent|JEvent]]<br />
|[[API16:JHtmlEmail|JHtmlEmail]]<br />
|[[API16:JSessionStorageApc|JSessionStorageApc]]<br />
|-<br />
|[[API16:JCacheCallback|JCacheCallback]]<br />
|[[API16:JException|JException]]<br />
|[[API16:JHtmlForm|JHtmlForm]]<br />
|[[API16:JSessionStorageDatabase|JSessionStorageDatabase]]<br />
|-<br />
|[[API16:JCacheOutput|JCacheOutput]]<br />
|[[API16:JExtension|JExtension]]<br />
|[[API16:JHtmlGrid|JHtmlGrid]]<br />
|[[API16:JSessionStorageEaccelerator|JSessionStorageEaccelerator]]<br />
|-<br />
|[[API16:JCachePage|JCachePage]]<br />
|[[API16:JFTP|JFTP]]<br />
|[[API16:JHtmlImage|JHtmlImage]]<br />
|[[API16:JSessionStorageMemcache|JSessionStorageMemcache]]<br />
|-<br />
|[[API16:JCacheStorage|JCacheStorage]]<br />
|[[API16:JFactory|JFactory]]<br />
|[[API16:JHtmlJGrid|JHtmlJGrid]]<br />
|[[API16:JSessionStorageNone|JSessionStorageNone]]<br />
|-<br />
|[[API16:JCacheStorageApc|JCacheStorageApc]]<br />
|[[API16:JFeedEnclosure|JFeedEnclosure]]<br />
|[[API16:JHtmlList|JHtmlList]]<br />
|[[API16:JSessionStorageXcache|JSessionStorageXcache]]<br />
|-<br />
|[[API16:JCacheStorageEaccelerator|JCacheStorageEaccelerator]]<br />
|[[API16:JFeedImage|JFeedImage]]<br />
|[[API16:JHtmlMenu|JHtmlMenu]]<br />
|[[API16:JSimpleCrypt|JSimpleCrypt]]<br />
|-<br />
|[[API16:JCacheStorageFile|JCacheStorageFile]]<br />
|[[API16:JFeedItem|JFeedItem]]<br />
|[[API16:JHtmlRules|JHtmlRules]]<br />
|[[API16:JSimpleXML|JSimpleXML]]<br />
|-<br />
|[[API16:JCacheStorageMemcache|JCacheStorageMemcache]]<br />
|[[API16:JFile|JFile]]<br />
|[[API16:JHtmlSelect|JHtmlSelect]]<br />
|[[API16:JSimpleXMLElement|JSimpleXMLElement]]<br />
|-<br />
|[[API16:JCacheStorageXCache|JCacheStorageXCache]]<br />
|[[API16:JFilesystemHelper|JFilesystemHelper]]<br />
|[[API16:JHtmlSliders|JHtmlSliders]]<br />
|[[API16:JStream|JStream]]<br />
|-<br />
|[[API16:JCacheView|JCacheView]]<br />
|[[API16:JFilterInput|JFilterInput]]<br />
|[[API16:JHtmlString|JHtmlString]]<br />
|[[API16:JStreamString|JStreamString]]<br />
|-<br />
|[[API16:JCategories|JCategories]]<br />
|[[API16:JFilterOutput|JFilterOutput]]<br />
|[[API16:JHtmlTabs|JHtmlTabs]]<br />
|[[API16:JString|JString]]<br />
|-<br />
|[[API16:JCategoryNode|JCategoryNode]]<br />
|[[API16:JFolder|JFolder]]<br />
|[[API16:JInstaller|JInstaller]]<br />
|[[API16:JStringController|JStringController]]<br />
|-<br />
|[[API16:JClientHelper|JClientHelper]]<br />
|[[API16:JForm|JForm]]<br />
|[[API16:JInstallerComponent|JInstallerComponent]]<br />
|[[API16:JTable|JTable]]<br />
|-<br />
|[[API16:JComponentHelper|JComponentHelper]]<br />
|[[API16:JFormField|JFormField]]<br />
|[[API16:JInstallerFile|JInstallerFile]]<br />
|[[API16:JTableAsset|JTableAsset]]<br />
|-<br />
|[[API16:JController|JController]]<br />
|[[API16:JFormFieldAccessLevel|JFormFieldAccessLevel]]<br />
|[[API16:JInstallerHelper|JInstallerHelper]]<br />
|[[API16:JTableCategory|JTableCategory]]<br />
|-<br />
|[[API16:JControllerForm|JControllerForm]]<br />
|[[API16:JFormFieldCacheHandler|JFormFieldCacheHandler]]<br />
|[[API16:JInstallerLanguage|JInstallerLanguage]]<br />
|[[API16:JTableContent|JTableContent]]<br />
|-<br />
|[[API16:JDatabase|JDatabase]]<br />
|[[API16:JFormFieldCalendar|JFormFieldCalendar]]<br />
|[[API16:JInstallerLibrary|JInstallerLibrary]]<br />
|[[API16:JTableExtension|JTableExtension]]<br />
|-<br />
|[[API16:JDatabaseMySQL|JDatabaseMySQL]]<br />
|[[API16:JFormFieldCategory|JFormFieldCategory]]<br />
|[[API16:JInstallerModule|JInstallerModule]]<br />
|[[API16:JTableMenu|JTableMenu]]<br />
|-<br />
|[[API16:JDatabaseMySQLi|JDatabaseMySQLi]]<br />
|[[API16:JFormFieldCheckbox|JFormFieldCheckbox]]<br />
|[[API16:JInstallerPackage|JInstallerPackage]]<br />
|[[API16:JTableMenuType|JTableMenuType]]<br />
|-<br />
|[[API16:JDatabaseQuery|JDatabaseQuery]]<br />
|[[API16:JFormFieldCombo|JFormFieldCombo]]<br />
|[[API16:JInstallerPlugin|JInstallerPlugin]]<br />
|[[API16:JTableModule|JTableModule]]<br />
|-<br />
|[[API16:JDatabaseQueryElement|JDatabaseQueryElement]]<br />
|[[API16:JFormFieldComponentLayout|JFormFieldComponentLayout]]<br />
|[[API16:JInstallerTemplate|JInstallerTemplate]]<br />
|[[API16:JTableNested|JTableNested]]<br />
|-<br />
|[[API16:JDate|JDate]]<br />
|[[API16:JFormFieldContentLanguage|JFormFieldContentLanguage]]<br />
|[[API16:JLDAP|JLDAP]]<br />
|[[API16:JTableSession|JTableSession]]<br />
|-<br />
|[[API16:JDispatcher|JDispatcher]]<br />
|[[API16:JFormFieldEditor|JFormFieldEditor]]<br />
|[[API16:JLanguage|JLanguage]]<br />
|[[API16:JTableUpdate|JTableUpdate]]<br />
|-<br />
|[[API16:JDocument|JDocument]]<br />
|[[API16:JFormFieldEditors|JFormFieldEditors]]<br />
|[[API16:JLanguageHelper|JLanguageHelper]]<br />
|[[API16:JTableUser|JTableUser]]<br />
|-<br />
|[[API16:JDocumentError|JDocumentError]]<br />
|[[API16:JFormFieldFile|JFormFieldFile]]<br />
|[[API16:JLanguageTransliterate|JLanguageTransliterate]]<br />
|[[API16:JTableUsergroup|JTableUsergroup]]<br />
|-<br />
|[[API16:JDocumentFeed|JDocumentFeed]]<br />
|[[API16:JFormFieldFileList|JFormFieldFileList]]<br />
|[[API16:JLibraryManifest|JLibraryManifest]]<br />
|[[API16:JTableViewlevel|JTableViewlevel]]<br />
|-<br />
|[[API16:JDocumentHTML|JDocumentHTML]]<br />
|[[API16:JFormFieldFolderList|JFormFieldFolderList]]<br />
|[[API16:JLog|JLog]]<br />
|[[API16:JText|JText]]<br />
|-<br />
|[[API16:JDocumentJSON|JDocumentJSON]]<br />
|[[API16:JFormFieldGroupedList|JFormFieldGroupedList]]<br />
|[[API16:JMail|JMail]]<br />
|[[API16:JToolBar|JToolBar]]<br />
|-<br />
|[[API16:JDocumentRAW|JDocumentRAW]]<br />
|[[API16:JFormFieldHelpsite|JFormFieldHelpsite]]<br />
|[[API16:JMailHelper|JMailHelper]]<br />
|[[API16:JTree|JTree]]<br />
|-<br />
|[[API16:JDocumentRenderer|JDocumentRenderer]]<br />
|[[API16:JFormFieldHidden|JFormFieldHidden]]<br />
|[[API16:JMenu|JMenu]]<br />
|[[API16:JURI|JURI]]<br />
|-<br />
|[[API16:JDocumentRendererAtom|JDocumentRendererAtom]]<br />
|[[API16:JFormFieldImageList|JFormFieldImageList]]<br />
|[[API16:JModel|JModel]]<br />
|[[API16:JUpdate|JUpdate]]<br />
|-<br />
|[[API16:JDocumentRendererComponent|JDocumentRendererComponent]]<br />
|[[API16:JFormFieldInteger|JFormFieldInteger]]<br />
|[[API16:JModelForm|JModelForm]]<br />
|[[API16:JUpdateAdapter|JUpdateAdapter]]<br />
|-<br />
|[[API16:JDocumentRendererHead|JDocumentRendererHead]]<br />
|[[API16:JFormFieldLanguage|JFormFieldLanguage]]<br />
|[[API16:JModelItem|JModelItem]]<br />
|[[API16:JUpdater|JUpdater]]<br />
|-<br />
|[[API16:JDocumentRendererMessage|JDocumentRendererMessage]]<br />
|[[API16:JFormFieldList|JFormFieldList]]<br />
|[[API16:JModelList|JModelList]]<br />
|[[API16:JUpdaterCollection|JUpdaterCollection]]<br />
|-<br />
|[[API16:JDocumentRendererModule|JDocumentRendererModule]]<br />
|[[API16:JFormFieldMedia|JFormFieldMedia]]<br />
|[[API16:JModuleHelper|JModuleHelper]]<br />
|[[API16:JUpdaterExtension|JUpdaterExtension]]<br />
|-<br />
|[[API16:JDocumentRendererModules|JDocumentRendererModules]]<br />
|[[API16:JFormFieldMediamanager|JFormFieldMediamanager]]<br />
|[[API16:JNode|JNode]]<br />
|[[API16:JUser|JUser]]<br />
|-<br />
|[[API16:JDocumentRendererRSS|JDocumentRendererRSS]]<br />
|[[API16:JFormFieldMenu|JFormFieldMenu]]<br />
|[[API16:JObject|JObject]]<br />
|[[API16:JUserHelper|JUserHelper]]<br />
|-<br />
|[[API16:JDocumentXML|JDocumentXML]]<br />
|[[API16:JFormFieldMenuItem|JFormFieldMenuItem]]<br />
|[[API16:JObservable|JObservable]]<br />
|[[API16:JUtility|JUtility]]<br />
|-<br />
|[[API16:JEditor|JEditor]]<br />
|[[API16:JFormFieldModuleLayout|JFormFieldModuleLayout]]<br />
|[[API16:JObserver|JObserver]]<br />
|[[API16:JVersion|JVersion]]<br />
|-<br />
|[[API16:JElement|JElement]]<br />
|[[API16:JFormFieldPassword|JFormFieldPassword]]<br />
|[[API16:JPackageManifest|JPackageManifest]]<br />
|[[API16:JView|JView]]<br />
|-<br />
|[[API16:JElementCalendar|JElementCalendar]]<br />
|[[API16:JFormFieldRadio|JFormFieldRadio]]<br />
|[[API16:JPagination|JPagination]]<br />
|[[API16:JXMLElement|JXMLElement]]<br />
|-<br />
|[[API16:JElementCategory|JElementCategory]]<br />
|[[API16:JFormFieldRules|JFormFieldRules]]<br />
|[[API16:JPaginationObject|JPaginationObject]]<br />
|<br />
|}<br />
==References==<br />
&lt;references/&gt;</div>Mvangeest//docs.joomla.org/API15:FrameworkAPI15:Framework2013-06-14T14:18:16Z<p>Mvangeest: Archive maintenance: a page move could have caused major confusion</p>
<hr />
<div>&lt;span class=&quot;editsection&quot; style=&quot;font-size:76%;&quot;&gt;<br />
&lt;nowiki&gt;[&lt;/nowiki&gt;[[Chunk:Framework (CMS 1.5 and 1.6)|Edit Descripton]]&lt;nowiki&gt;]&lt;/nowiki&gt;<br />
&lt;/span&gt;<br />
{{Chunk:Framework (CMS 1.5 and 1.6)}}<br />
<br />
{| class=&quot;wikitable&quot;<br />
|-<br />
|-<br />
|[[API15:JApplication|JApplication]]<br />
|[[API15:JDocumentRenderer|JDocumentRenderer]]<br />
|[[API15:JHTMLContent|JHTMLContent]]<br />
|[[API15:JRegistryFormatPHP|JRegistryFormatPHP]]<br />
|-<br />
|[[API15:JApplicationHelper|JApplicationHelper]]<br />
|[[API15:JDocumentRendererAtom|JDocumentRendererAtom]]<br />
|[[API15:JHTMLEmail|JHTMLEmail]]<br />
|[[API15:JRegistryFormatXML|JRegistryFormatXML]]<br />
|-<br />
|[[API15:JArchive|JArchive]]<br />
|[[API15:JDocumentRendererComponent|JDocumentRendererComponent]]<br />
|[[API15:JHTMLForm|JHTMLForm]]<br />
|[[API15:JRequest|JRequest]]<br />
|-<br />
|[[API15:JArchiveBzip2|JArchiveBzip2]]<br />
|[[API15:JDocumentRendererHead|JDocumentRendererHead]]<br />
|[[API15:JHTMLGrid|JHTMLGrid]]<br />
|[[API15:JResponse|JResponse]]<br />
|-<br />
|[[API15:JArchiveGzip|JArchiveGzip]]<br />
|[[API15:JDocumentRendererMessage|JDocumentRendererMessage]]<br />
|[[API15:JHTMLImage|JHTMLImage]]<br />
|[[API15:JRoute|JRoute]]<br />
|-<br />
|[[API15:JArchiveTar|JArchiveTar]]<br />
|[[API15:JDocumentRendererModule|JDocumentRendererModule]]<br />
|[[API15:JHTMLList|JHTMLList]]<br />
|[[API15:JRouter|JRouter]]<br />
|-<br />
|[[API15:JArchiveZip|JArchiveZip]]<br />
|[[API15:JDocumentRendererModules|JDocumentRendererModules]]<br />
|[[API15:JHTMLMenu|JHTMLMenu]]<br />
|[[API15:JSession|JSession]]<br />
|-<br />
|[[API15:JArrayHelper|JArrayHelper]]<br />
|[[API15:JDocumentRendererRSS|JDocumentRendererRSS]]<br />
|[[API15:JHTMLSelect|JHTMLSelect]]<br />
|[[API15:JSessionStorage|JSessionStorage]]<br />
|-<br />
|[[API15:JAuthentication|JAuthentication]]<br />
|[[API15:JEditor|JEditor]]<br />
|[[API15:JHelp|JHelp]]<br />
|[[API15:JSessionStorageApc|JSessionStorageApc]]<br />
|-<br />
|[[API15:JAuthenticationResponse|JAuthenticationResponse]]<br />
|[[API15:JElement|JElement]]<br />
|[[API15:JInstaller|JInstaller]]<br />
|[[API15:JSessionStorageDatabase|JSessionStorageDatabase]]<br />
|-<br />
|[[API15:JAuthorization|JAuthorization]]<br />
|[[API15:JElementCalendar|JElementCalendar]]<br />
|[[API15:JInstallerComponent|JInstallerComponent]]<br />
|[[API15:JSessionStorageEaccelerator|JSessionStorageEaccelerator]]<br />
|-<br />
|[[API15:JBrowser|JBrowser]]<br />
|[[API15:JElementCategory|JElementCategory]]<br />
|[[API15:JInstallerHelper|JInstallerHelper]]<br />
|[[API15:JSessionStorageMemcache|JSessionStorageMemcache]]<br />
|-<br />
|[[API15:JBuffer|JBuffer]]<br />
|[[API15:JElementEditors|JElementEditors]]<br />
|[[API15:JInstallerLanguage|JInstallerLanguage]]<br />
|[[API15:JSessionStorageNone|JSessionStorageNone]]<br />
|-<br />
|[[API15:JButton|JButton]]<br />
|[[API15:JElementFilelist|JElementFilelist]]<br />
|[[API15:JInstallerModule|JInstallerModule]]<br />
|[[API15:JSessionStorageXcache|JSessionStorageXcache]]<br />
|-<br />
|[[API15:JButtonConfirm|JButtonConfirm]]<br />
|[[API15:JElementFolderlist|JElementFolderlist]]<br />
|[[API15:JInstallerPlugin|JInstallerPlugin]]<br />
|[[API15:JSimpleCrypt|JSimpleCrypt]]<br />
|-<br />
|[[API15:JButtonCustom|JButtonCustom]]<br />
|[[API15:JElementHelpsites|JElementHelpsites]]<br />
|[[API15:JInstallerTemplate|JInstallerTemplate]]<br />
|[[API15:JSimpleXML|JSimpleXML]]<br />
|-<br />
|[[API15:JButtonHelp|JButtonHelp]]<br />
|[[API15:JElementHidden|JElementHidden]]<br />
|[[API15:JLDAP|JLDAP]]<br />
|[[API15:JSimpleXMLElement|JSimpleXMLElement]]<br />
|-<br />
|[[API15:JButtonLink|JButtonLink]]<br />
|[[API15:JElementImageList|JElementImageList]]<br />
|[[API15:JLanguage|JLanguage]]<br />
|[[API15:JString|JString]]<br />
|-<br />
|[[API15:JButtonPopup|JButtonPopup]]<br />
|[[API15:JElementLanguages|JElementLanguages]]<br />
|[[API15:JLanguageHelper|JLanguageHelper]]<br />
|[[API15:JTable|JTable]]<br />
|-<br />
|[[API15:JButtonSeparator|JButtonSeparator]]<br />
|[[API15:JElementList|JElementList]]<br />
|[[API15:JLog|JLog]]<br />
|[[API15:JTableARO|JTableARO]]<br />
|-<br />
|[[API15:JButtonStandard|JButtonStandard]]<br />
|[[API15:JElementMenu|JElementMenu]]<br />
|[[API15:JMail|JMail]]<br />
|[[API15:JTableAROGroup|JTableAROGroup]]<br />
|-<br />
|[[API15:JCache|JCache]]<br />
|[[API15:JElementMenuItem|JElementMenuItem]]<br />
|[[API15:JMailHelper|JMailHelper]]<br />
|[[API15:JTableCategory|JTableCategory]]<br />
|-<br />
|[[API15:JCacheCallback|JCacheCallback]]<br />
|[[API15:JElementPassword|JElementPassword]]<br />
|[[API15:JMenu|JMenu]]<br />
|[[API15:JTableComponent|JTableComponent]]<br />
|-<br />
|[[API15:JCacheOutput|JCacheOutput]]<br />
|[[API15:JElementRadio|JElementRadio]]<br />
|[[API15:JModel|JModel]]<br />
|[[API15:JTableContent|JTableContent]]<br />
|-<br />
|[[API15:JCachePage|JCachePage]]<br />
|[[API15:JElementSQL|JElementSQL]]<br />
|[[API15:JModuleHelper|JModuleHelper]]<br />
|[[API15:JTableMenu|JTableMenu]]<br />
|-<br />
|[[API15:JCacheStorage|JCacheStorage]]<br />
|[[API15:JElementSection|JElementSection]]<br />
|[[API15:JNode|JNode]]<br />
|[[API15:JTableMenuTypes|JTableMenuTypes]]<br />
|-<br />
|[[API15:JCacheStorageApc|JCacheStorageApc]]<br />
|[[API15:JElementSpacer|JElementSpacer]]<br />
|[[API15:JObject|JObject]]<br />
|[[API15:JTableModule|JTableModule]]<br />
|-<br />
|[[API15:JCacheStorageEaccelerator|JCacheStorageEaccelerator]]<br />
|[[API15:JElementText|JElementText]]<br />
|[[API15:JObservable|JObservable]]<br />
|[[API15:JTablePlugin|JTablePlugin]]<br />
|-<br />
|[[API15:JCacheStorageFile|JCacheStorageFile]]<br />
|[[API15:JElementTextarea|JElementTextarea]]<br />
|[[API15:JObserver|JObserver]]<br />
|[[API15:JTableSection|JTableSection]]<br />
|-<br />
|[[API15:JCacheStorageMemcache|JCacheStorageMemcache]]<br />
|[[API15:JElementTimezones|JElementTimezones]]<br />
|[[API15:JPagination|JPagination]]<br />
|[[API15:JTableSession|JTableSession]]<br />
|-<br />
|[[API15:JCacheStorageXCache|JCacheStorageXCache]]<br />
|[[API15:JElementUserGroup|JElementUserGroup]]<br />
|[[API15:JPaginationObject|JPaginationObject]]<br />
|[[API15:JTableUser|JTableUser]]<br />
|-<br />
|[[API15:JCacheView|JCacheView]]<br />
|[[API15:JError|JError]]<br />
|[[API15:JPane|JPane]]<br />
|[[API15:JTemplate|JTemplate]]<br />
|-<br />
|[[API15:JClientHelper|JClientHelper]]<br />
|[[API15:JEvent|JEvent]]<br />
|[[API15:JPaneSliders|JPaneSliders]]<br />
|[[API15:JText|JText]]<br />
|-<br />
|[[API15:JComponentHelper|JComponentHelper]]<br />
|[[API15:JException|JException]]<br />
|[[API15:JPaneTabs|JPaneTabs]]<br />
|[[API15:JToolBar|JToolBar]]<br />
|-<br />
|[[API15:JController|JController]]<br />
|[[API15:JFTP|JFTP]]<br />
|[[API15:JParameter|JParameter]]<br />
|[[API15:JTree|JTree]]<br />
|-<br />
|[[API15:JDatabase|JDatabase]]<br />
|[[API15:JFactory|JFactory]]<br />
|[[API15:JPath|JPath]]<br />
|[[API15:JURI|JURI]]<br />
|-<br />
|[[API15:JDatabaseMySQL|JDatabaseMySQL]]<br />
|[[API15:JFeedEnclosure|JFeedEnclosure]]<br />
|[[API15:JPathway|JPathway]]<br />
|[[API15:JUser|JUser]]<br />
|-<br />
|[[API15:JDatabaseMySQLi|JDatabaseMySQLi]]<br />
|[[API15:JFeedImage|JFeedImage]]<br />
|[[API15:JPlugin|JPlugin]]<br />
|[[API15:JUserHelper|JUserHelper]]<br />
|-<br />
|[[API15:JDate|JDate]]<br />
|[[API15:JFeedItem|JFeedItem]]<br />
|[[API15:JPluginHelper|JPluginHelper]]<br />
|[[API15:JUtility|JUtility]]<br />
|-<br />
|[[API15:JDispatcher|JDispatcher]]<br />
|[[API15:JFile|JFile]]<br />
|[[API15:JProfiler|JProfiler]]<br />
|[[API15:JVersion|JVersion]]<br />
|-<br />
|[[API15:JDocument|JDocument]]<br />
|[[API15:JFilterInput|JFilterInput]]<br />
|[[API15:JQuery|JQuery]]<br />
|[[API15:JView|JView]]<br />
|-<br />
|[[API15:JDocumentError|JDocumentError]]<br />
|[[API15:JFilterOutput|JFilterOutput]]<br />
|[[API15:JQueryElement|JQueryElement]]<br />
|[[API15:patTemplate_Function_Sef|patTemplate_Function_Sef]]<br />
|-<br />
|[[API15:JDocumentFeed|JDocumentFeed]]<br />
|[[API15:JFolder|JFolder]]<br />
|[[API15:JRecordSet|JRecordSet]]<br />
|[[API15:patTemplate_Function_Translate|patTemplate_Function_Translate]]<br />
|-<br />
|[[API15:JDocumentHTML|JDocumentHTML]]<br />
|[[API15:JFrameworkConfig|JFrameworkConfig]]<br />
|[[API15:JRegistry|JRegistry]]<br />
|[[API15:patTemplate_Modifier_SEF|patTemplate_Modifier_SEF]]<br />
|-<br />
|[[API15:JDocumentPDF|JDocumentPDF]]<br />
|[[API15:JHTML|JHTML]]<br />
|[[API15:JRegistryFormat|JRegistryFormat]]<br />
|[[API15:patTemplate_Modifier_Translate|patTemplate_Modifier_Translate]]<br />
|-<br />
|[[API15:JDocumentRAW|JDocumentRAW]]<br />
|[[API15:JHTMLBehavior|JHTMLBehavior]]<br />
|[[API15:JRegistryFormatINI|JRegistryFormatINI]]<br />
|<br />
|}<br />
==Reference==<br />
&lt;references/&gt;</div>Mvangeest//docs.joomla.org/Joomla!_Framework_(CMS_1.5_and_1.6)_vs_Joomla!_PlatformJoomla! Framework (CMS 1.5 and 1.6) vs Joomla! Platform2013-06-14T14:15:46Z<p>Mvangeest: Adjusted link after page move</p>
<hr />
<div>{{review}}<br />
== Framework ==<br />
{{Chunk:Framework (CMS 1.5 and 1.6)}}<br />
== Introduction to Platform ==<br />
{{Chunk:Platform}}<br />
== Differences ==<br />
The Joomla! Platform can now be used to build other CMS Applications or Web and command line Applications specific to a developer's needs such as eCommerce, Social Media, and other stand alone Applications. The Platform is stored on GitHub, which allows developers to easily fork the Platform code for their own purposes, and then if they want, integrate it into the main code branch. This will encourage more developers and even attract larger corporations to contribute to the Joomla! Platform who might not have done so before.&lt;ref&gt;http://magazine.joomla.org/issues/Issue-Dec-2011/item/616-Write-your-own-App-using-Joomla-Platform?tmpl=component&amp;print=1&lt;/ref&gt; <br />
<br />
Another good thing about the separation of the the Joomla! Platform it has a release schedule of every 3 months which allows for a faster integration of core features used by extension developers. The version number is determined by the the year of its release. For example, Joomla! Platform 11.1 was released in 2011 and 12.1 was released in 2012.&lt;ref&gt;http://magazine.joomla.org/issues/Issue-Dec-2011/item/616-Write-your-own-App-using-Joomla-Platform?tmpl=component&amp;print=1&lt;/ref&gt;<br />
== See also and References ==<br />
&lt;references/&gt;<br />
&lt;noinclude&gt;[[Category:Platform]][[Category:Framework]][[Category:Frameworks and Platforms]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Chunk:Framework_(CMS_1.5_and_1.6)Chunk:Framework (CMS 1.5 and 1.6)2013-06-14T14:14:19Z<p>Mvangeest: Mvangeest moved page Chunk:Framework to Chunk:Framework (CMS 1.5 and 1.6): The name Framework has been reused for the new Joomla Framework project</p>
<hr />
<div>&lt;noinclude&gt;{{chunk}}&lt;/noinclude&gt;__NOTOC__<br />
{|<br />
|-<br />
|The Joomla! Framework&lt;ref&gt;See also [[Subpackages]]&lt;/ref&gt; was an important part of the [[CMS Architecture in 1.5 and 1.6|Joomla! CMS architecture in the versions 1.5 and 1.6]]. It was based on modern object-oriented design patterns that make the Joomla core highly maintainable and easily extendable. Between April and July 2011, the Framework was rebranded as the Joomla! [[Platform]] and is now being developed separately from the Joomla! [[CMS]]. The first version of the CMS to ship with the Platform was version [[:Category:Joomla! 1.7|1.7]].<br />
<br />
Third party developers benefit from the rich, and easily accessible functionality that the Joomla Framework provides.<br />
|[[Image:JoomlaArchitecture0.png|thumb|425px|The Joomla Architecture]]<br />
|}<br />
&lt;noinclude&gt;&lt;references/&gt;&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Chunk:FrameworkChunk:Framework2013-06-14T14:14:19Z<p>Mvangeest: Mvangeest moved page Chunk:Framework to Chunk:Framework (CMS 1.5 and 1.6): The name Framework has been reused for the new Joomla Framework project</p>
<hr />
<div>#REDIRECT [[Chunk:Framework (CMS 1.5 and 1.6)]]</div>Mvangeest//docs.joomla.org/User:Enav/BeginnersUser:Enav/Beginners2013-03-17T21:00:51Z<p>Mvangeest: Mvangeest moved page Enav/Beginners to User:Enav/Beginners: Moved page to the User namespace after user request</p>
<hr />
<div>Welcome to Joomla!, a leading open source Content Management System (CMS) platform. Joomla! is a well-tested, extensible and effective tool supported by a very active and friendly community of developers and users.<br />
<br />
This page contain several articles to quickly help you understand the basics of Joomla, and be able to create basic Joomla sites in a short time.<br />
<br />
== What is Joomla? ==<br />
<br />
If you are a boy from the old school (1990 ish) you may think that web sites still work with a bunch of linked HTML files, Not anymore buddy!, Welcome to century XXI! modern websites runs over Content Management Systems (CMS), this systems runs using dynamic languages like PHP and databases like MySQL databases, this way a CMS can store and manage huge amount of data like thousand of news articles articles.<br />
<br />
So in short Joomla is a very flexible CMS that runs on PHP that uses MySQL databases to store the data and let you create websites with dynamic content that will change and adjust to the context or the configuration parameters you provide.<br />
<br />
== Play with it ==<br />
<br />
Do you want to get started with Joomla!, but you have no idea where to begin? If so, you have come to the right place. The fastest way to learn about Joomla is to start paying with it right now. Visit the demo page and take few minutes to see the demo content and play with the configurations.<br />
<br />
Yes right here---&gt; [http://demo.joomla.org/ Joomla demo page]<br />
<br />
The first 2 term you need to learn are &quot;Frontend&quot; and &quot;Backend&quot;, the Frontent is the part that shows your site content and all the funny stuff and the Backend is the part that contains the configuration views and it is also the place where you normally manage (create, edit, update) your content. To access to your Joomla site Backend you just need to add the &quot;/administrators&quot; to your Joomla site path in the browser address bar i.e.: <br />
<br />
www.example.com/adminisrator<br />
<br />
Now that you know how Joomla looks and feel in the frontend and backend is time to you to learn what kind of magic you can do with this new tool of yours.<br />
<br />
Note: On the demo page you can chose to use a free trial hosting account, when the trial period expired if you chose to contract a paid hosting account with them, the Joomla! Project will receive a royalty for the transaction, consider this option if you would like to support the project.<br />
<br />
== What can i do with it? ==<br />
<br />
Joomla is a CMS, a system to manage content, To make a small analogy you can compare Joomla with a computer operative system, for example, on your computer the operative system manages the resources of your computer, also you can install applications to do more things on your computer, in this order of ideas Joomla is the one who is in charge to manage the data and you can install &quot;extensions&quot; to extend and enhance the functions of Joomla. <br />
<br />
Joomla comes by default with a bunch of extensions pre-installed and pre-configured to make Joomla works as a News website, but you can manually configure your Joomla site to easily make it works as a:<br />
<br />
* Blog site<br />
* Company or Government site<br />
* Contact directory<br />
* Simple product Catalog<br />
<br />
Now if your interest is to create more complex sites like:<br />
<br />
* eCommerce sites with shopping cart<br />
* Support sites with forums and ticket systems<br />
* News sites with paid subscription system and comment systems<br />
* e-learning sites with paid subscription systems<br />
<br />
Then you need to install more Joomla extensions to make your vanilla Joomla site work the way you need. Lots and lots of extensions are for free with no cost at all, and others are extensions commercial, this means that you need to pay a fee to have the right to use them but the normally commercial extensions comes with a tech support deals that will help you save precious time and money, and everybody knows time is gold.<br />
<br />
Here at [http://extensions.joomla.org/ The Joomla Extension Directory] you have thousands of extensions to chose from, take some time to visit the directory and do few searches for the sake to get familiarized with it, you may need to use some more extensions in the future if you decide to [http://www.youtube.com/watch?v=HYtbEmO_JC4 pimp up] your Joomla site.<br />
<br />
Maybe a client or your boss is asking you for a web solution with a very specific set of requirements and the information so far does not help you to determine if Joomla is suitable for the job, in order to help you to save some time feel free to visit the Joomla community people and make your questions to humans at:<br />
<br />
* The official [http://forum.joomla.org/ Joomla Forums]<br />
* The official [http://webchat.freenode.net/?channels=joomla ##Joomla] IRC channel (aka chat room)<br />
* The official [http://www.facebook.com/groups/joomlanospam/ Facebook group]<br />
<br />
== Installing Joomla! ==<br />
<br />
Now that you had enough fun playing with the Joomla demo site you may want to go the next level and start messing around with extensions and templates to see how they do in your very own local test server or your rented web server.<br />
<br />
Follow one of this tutorials that suits you better.<br />
<br />
* [[Installing Joomla on a rented web server]]<br />
* [[Installing Joomla on a local web server]]<br />
<br />
Note: This tutorials are targeted for non-expert audience, if you need more detailed and advanced information go to the [[developers | Developers page]].<br />
<br />
== Understanding How Joomla Works ==<br />
<br />
To keep this introductory article as short and friendly as possible we can say that Joomla have tow main parts, the Frontend and the Backend, as explained before the Frontend shows the site content that any visitor can see and the Backend is the administrative part that is normally restricted for users with privileges such as administrators.<br />
<br />
Taking a quick look at the average website we can conclude that most of them have this basic layout:<br />
<br />
* Header<br />
* Main menu<br />
* Main content<br />
* Side content (left or right of main content)<br />
* Footer<br />
<br />
In Joomla a template is the one in charge to determine the layout and disposition of those chunks of data described in the previous list, also a template is the one used to determine the font types, colors, styles and the presentation in general.<br />
<br />
Now you may wonder what is used to render each of those chunks of data, and the answer is modules and components. Joomla depends on extensions (components, modules, plugins) to render chunks of information that have certain characteristics, for example, for small and compact chunks of data like header, main menu, side content and footer Joomla uses Modules who are meant to be use for that kind of data, but for the main content of the page that tend to be a very large and dynamic chunk of data, the element in use is the component.<br />
<br />
There are several kinds of plugins and they are categorized depending on the job they do, For example, A content plugin can be used to manipulate data before it is rendered on the page, an authentication plugin is a plugin that can give you the ability to login in a Joomla site using Google accounts or Facebook accounts.<br />
<br />
In resume:<br />
<br />
* Templates: Defines the site layout and visual styles.<br />
* Component: Used to render large chucks of dynamic data.<br />
* Modules: Used to render compact and normally static chunks of data.<br />
* Plugins: They are used to extend the Joomla functions and manipulate data.<br />
<br />
Both the frontend and the backend uses templates and extensions. Is a normal thing that many Joomla sites uses different templates on the frontend and leave the backend with the default template but you can always install a custom 3rd party template for the backend to have a different look and feel.<br />
<br />
Note: Since most developers creates extensions based on how the default administrative template looks and work you may experience bugs and visual glitches with 3rd party administrative templates, so we recommend the use of the default Joomla template, most tutorials and documentation screenshots in general are based on the default Joomla administrative template.</div>Mvangeest//docs.joomla.org/Enav/BeginnersEnav/Beginners2013-03-17T21:00:51Z<p>Mvangeest: Mvangeest moved page Enav/Beginners to User:Enav/Beginners: Moved page to the User namespace after user request</p>
<hr />
<div>#REDIRECT [[User:Enav/Beginners]]</div>Mvangeest//docs.joomla.org/Manifest_filesManifest files2013-01-22T23:00:42Z<p>Mvangeest: /* Root element */ Corrected and (partly) updated information</p>
<hr />
<div>{{incomplete}}<br />
{{RightTOC}}<br />
==Introduction==<br />
Within Joomla there are manifest files for all of the extensions. These files include the general installation information as well as parameters for the configuration of the [[extension]] itself. Since Joomla! 1.6 {{JVer|1.6}}, there are very few differences between the manifest file formats for the different [[Extension types (technical definitions)|types of extensions]], allowing each type to access the full power of the Joomla! installer.<br />
<br />
==Naming conventions==<br />
The file must be named &lt;tt&gt;manifest.xml&lt;/tt&gt; or &lt;tt&gt;&lt;extension_name&gt;.xml&lt;/tt&gt; and located in the root directory of the installation package.<br />
<br />
==Syntax==<br />
<br />
=== Root element ===<br />
The primary tag of the installation file is: <br />
&lt;source lang=xml&gt;&lt;extension&gt;&lt;/extension&gt;&lt;/source&gt;<br />
<br />
This starting and closing tags are now valid for all extensions. The new tag &lt;code&gt;&lt;extension&gt;&lt;/code&gt; replaces the old &lt;code&gt;&lt;install&gt;&lt;/install&gt;&lt;/code&gt; from Joomla {{JVer|1.5}}. The following attributes are allowed within the tag:<br />
<br />
{|class=&quot;wikitable&quot;<br />
|-<br />
! style=&quot;width: 150px&quot; | Attribute || style=&quot;width: 150px&quot; | Values || Applicable&amp;nbsp;to || Description<br />
|-<br />
| type || &lt;code&gt;component&lt;/code&gt;&lt;br /&gt;&lt;code&gt;file&lt;/code&gt;&lt;br /&gt;&lt;code&gt;language&lt;/code&gt;&lt;br /&gt;&lt;code&gt;library&lt;/code&gt;&lt;br /&gt;&lt;code&gt;module&lt;/code&gt;&lt;br /&gt;&lt;code&gt;package&lt;/code&gt;&lt;br /&gt;&lt;code&gt;plugin&lt;/code&gt;&lt;br /&gt;&lt;code&gt;template&lt;/code&gt; || All extensions<br />
| This attribute describes the type of the extension for the installer. Based on this type further requirements to sub-tags apply.<br />
|-<br />
| version<br />
| &lt;code&gt;2.5&lt;/code&gt; || All extensions<br />
| String that identifies the version of Joomla for which this extension is developed.<br />
|-<br />
| method<br />
| &lt;code&gt;install&lt;/code&gt;&lt;br /&gt;&lt;code&gt;upgrade&lt;/code&gt; || All extensions<br />
| The default value &lt;code&gt;install&lt;/code&gt; will be also used if the method attribute is not used. The &lt;code&gt;install&lt;/code&gt; value means the installer will gracefully stop if it finds any existing file/folder of the new extension.<br />
|-<br />
| client<br />
| &lt;code&gt;site&lt;/code&gt;&lt;br /&gt;&lt;code&gt;administrator&lt;/code&gt; || Modules<br />
| The client attribute allows you to specify for which application client the new module is available.<br />
|-<br />
| group<br />
| ''string'' || Plugins<br />
| The group name specifies for which group of plugins the new plugin is available. The existing groups are the folder names within the directory &lt;tt&gt;/plugins&lt;/tt&gt;. The installer will create new folder names for group names that do not exist yet.<br />
|}<br />
<br />
=== Metadata ===<br />
<br />
The following elements can be used to insert metadata. None of these elements are required; if they are present, they must be a child of the root element.<br />
<br />
* &lt;code&gt;&lt;name&gt;&lt;/code&gt; &amp;ndash; raw component name (e.g. &lt;code&gt;com_banners&lt;/code&gt;)<br />
* &lt;code&gt;&lt;author&gt;&lt;/code&gt; &amp;ndash; author's name (e.g. &lt;code&gt;Joomla! Project&lt;/code&gt;)<br />
* &lt;code&gt;&lt;creationDate&gt;&lt;/code&gt; &amp;ndash; date of creation or release (e.g. &lt;code&gt;April 2006&lt;/code&gt;)<br />
* &lt;code&gt;&lt;copyright&gt;&lt;/code&gt; &amp;ndash; a copyright statement (e.g. &lt;code&gt;(C) 2005 - 2011 Open Source Matters. All rights reserved.&lt;/code&gt;)<br />
* &lt;code&gt;&lt;license&gt;&lt;/code&gt; &amp;ndash; a license statement (e.g. &lt;code&gt;NU General Public License version 2 or later; see LICENSE.txt&lt;/code&gt;)<br />
* &lt;code&gt;&lt;authorEmail&gt;&lt;/code&gt; &amp;ndash; author's email address (e.g. &lt;code&gt;&lt;nowiki&gt;admin@joomla.org&lt;/nowiki&gt;&lt;/code&gt;)<br />
* &lt;code&gt;&lt;authorUrl&gt;&lt;/code&gt; &amp;ndash; URL to the author's website (e.g. &lt;code&gt;&lt;nowiki&gt;www.joomla.org&lt;/nowiki&gt;&lt;/code&gt;)<br />
* &lt;code&gt;&lt;version&gt;&lt;/code&gt; &amp;ndash; the version number of the extension (e.g. &lt;code&gt;1.6.0&lt;/code&gt;)<br />
* &lt;code&gt;&lt;description&gt;&lt;/code&gt; &amp;ndash; the description of the component. This is a translatable field. (e.g. &lt;code&gt;COM_BANNERS_XML_DESCRIPTION&lt;/code&gt;)<br />
<br />
=== Front-end files ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;files folder=&quot;from-folder&quot;&gt;<br />
&lt;filename&gt;example.php&lt;/filename&gt;<br />
&lt;folder&gt;examples&lt;/folder&gt;<br />
&lt;/files&gt;<br />
&lt;/source&gt;<br />
<br />
Files to copy to the front-end directory should be placed in the &lt;code&gt;&lt;files&gt;&lt;/code&gt; element. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from'''. Each file to copy must be represented by a &lt;code&gt;&lt;filename&gt;&lt;/code&gt; element. If you want to copy an entire folder at once, you can define it as a &lt;code&gt;&lt;folder&gt;&lt;/code&gt;.<br />
<br />
=== Media files ===<br />
<br />
&lt;source lang=&quot;xml&gt;<br />
&lt;media folder=&quot;media&quot; destination=&quot;com_example&quot;&gt;<br />
&lt;filename&gt;com_example_logo.png&lt;/filename&gt;<br />
&lt;folder&gt;css&lt;/folder&gt;<br />
&lt;folder&gt;js&lt;/folder&gt;<br />
&lt;/media&gt;<br />
&lt;/source&gt;<br />
<br />
This example will copy the file(s) (&lt;tt&gt;/media/com_example_logo.png&lt;/tt&gt;) and folders ( &lt;tt&gt;/media/css/&lt;/tt&gt; and &lt;tt&gt;/media/js/&lt;/tt&gt; ) listed to &lt;tt&gt;/media/com_example/&lt;/tt&gt;, creating the &lt;tt&gt;com_example&lt;/tt&gt; folder if required. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from''' (in this case, &lt;tt&gt;media&lt;/tt&gt;).<br />
<br />
Extensions should be storing assets they need to be web accessible (JS, CSS, images etc) in &lt;code&gt;media&lt;/code&gt;. Amongst other things this feature was added as step in the progression to multi-site support and the eventual move of code files (PHP) out of the web accessible areas of the server.<br />
<br />
Ref:<br />
* [https://groups.google.com/forum/#!msg/joomla-dev-cms/4CAASJqFY-k/PvPj14gP29EJ Google Groups - joomla-dev-cms thread]<br />
* [https://groups.google.com/forum/#!msg/joomla-dev-cms/uNmhX98sKbE/p8p68Jke680J Google Groups - joomla-dev-cms thread]<br />
<br />
=== Administration section ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;administration&gt;<br />
&lt;!-- various elements --&gt;<br />
&lt;/administration&gt;<br />
&lt;/source&gt;<br />
<br />
The administration section is defined in the &lt;code&gt;&lt;administration&gt;&lt;/code&gt; element. Since only [[Component|components]] apply to both the [[Site (Application)|site]] and the [[Administrator (Application)|administrator]], '''only component manifests can include this element'''.<br />
<br />
==== Back-end files ====<br />
<br />
Files to copy to the back-end directory should be placed in the &lt;code&gt;&lt;files&gt;&lt;/code&gt; element under the &lt;code&gt;&lt;administration&gt;&lt;/code&gt;. You can use the optional &lt;code&gt;folder&lt;/code&gt; attribute to specify a directory '''in the ZIP package''' to copy '''from'''. See ''Front-end files'' for further rules.<br />
<br />
==== Menu links and submenus ====<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;menu&gt;COM_EXAMPLE&lt;/menu&gt;<br />
&lt;submenu&gt;<br />
&lt;menu link=&quot;anoption=avalue&quot;&gt;COM_EXAMPLE_SUBMENU_ANOPTION&lt;/menu&gt;<br />
&lt;menu view=&quot;viewname&quot;&gt;COM_EXAMPLE_SUBMENU_VIEWNAME&lt;/menu&gt;<br />
&lt;/submenu&gt;<br />
&lt;/source&gt;<br />
<br />
The text for the main menu item for the component is defined in the &lt;code&gt;&lt;menu&gt;&lt;/code&gt; item, a child of &lt;code&gt;&lt;administration&gt;&lt;/code&gt;. A &lt;code&gt;&lt;submenu&gt;&lt;/code&gt; element may also be present (also a child of &lt;code&gt;&lt;administration&gt;&lt;/code&gt;), which may contain more menu items defined by &lt;code&gt;&lt;menu&gt;&lt;/code&gt;.<br />
<br />
Additionally, each &lt;code&gt;&lt;menu&gt;&lt;/code&gt; item can define the following attributes:<br />
<br />
{| class=&quot;wikitable&quot;<br />
! style=&quot;width: 150px&quot; | Attribute || Description<br />
|-<br />
| link || A link to send the user to when the menu item is clicked<br />
|-<br />
| img || The (relative) path to an image (16x16 pixels) to appear beside the menu item. <br />
&lt;u&gt;Must be an url compatible as a file too (e.g. no spaces) !&lt;/u&gt;<br />
| alt ||<br />
|-<br />
| ''string'' || An URL parameter to add to the link. For example, &lt;code&gt;&lt;menu view=&quot;cpanel&quot;&gt;COM_EXAMPLE&lt;/menu&gt;&lt;/code&gt; in com_example's XML manifest would cause the URL of the menu item to be &lt;tt&gt;index.php?option=com_example&amp;view=cpanel&lt;/tt&gt;.<br />
|-<br />
|}<br />
<br />
The value inside the tag is the menu's label. Unlike Joomla! 1.5, you can not use a natural language string. For example, if you would enter &quot;Example Component&quot; instead of COM_EXAMPLE, it would result in your component name appearing as example-component in the menu and you would be unable to provide a translation. In order to provide a translation you need to create a file named en-GB.com_example.sys.ini in administrator/languages/en-GB (you can use the manifest's &lt;code&gt;&lt;languages&gt;&lt;/code&gt; tag to copy it during installation) or in administrator/components/com_example/language/en-GB. In the latter case, you must not include the translation file in the &lt;code&gt;&lt;languages&gt;&lt;/code&gt; tag. As long as you have placed the language directory in your &lt;code&gt;&lt;files&gt;&lt;/code&gt; tag, it will be copied along when the component is being installed.<br />
<br />
The contents of that file should be:<br />
&lt;source&gt;<br />
COM_EXAMPLE=&quot;Example Component&quot;<br />
COM_EXAMPLE_SUBMENU_ANOPTION=&quot;Another Option&quot;<br />
COM_EXAMPLE_SUBMENU_VIEWNAME=&quot;Another View&quot;<br />
<br />
&lt;/source&gt;<br />
<br />
Please note that the language string must be enclosed in double quotes, as per Joomla!'s translation standards. Important note: Joomla! 1.6 and later sorts the Component menu items based on the actual translation of the key you supply in your XML manifest. This means that the sorting order is correct no matter what you call your translation key and no matter which language the site is being displayed in. Essentially, Joomla! 1.6 fixed the wrong sorting of the Components menu for the majority (non-English speaking!) of Joomla! users experienced under Joomla! 1.5.<br />
<br />
{{Needsinfo|In Platform 11.1 no alt attribute processed and if link provide in menu tag other provided attributes were ignore. The other tags are task, view, controller, act, layout, sub. Please confirm this, please.}}<br />
<br />
=== Configuration ===<br />
{{warning|Components '''do not support''' configuration definitions '''in the manifest'''. This is a way implemented in Joomla! 1.5. They can define configuration options for multiple levels using [[Component configuration metadata]].}}<br />
The &lt;code&gt;&lt;config&gt;&lt;/code&gt; element, a child of the root, describes the configuration options for the extension. If applicable, the options will be shown by the appropriate Manager (Plugin Manager, Module Manager or Template Manager). '''Configuration options can also be defined in a separate file named &lt;code&gt;config.xml&lt;/code&gt;. Its root element should be &lt;code&gt;&lt;config&gt;&lt;/code&gt;.'''<br />
<br />
{{:XML JForm form definitions}}<br />
<br />
=== SQL ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;install folder=&quot;admin&quot;&gt;<br />
&lt;sql&gt;<br />
&lt;file driver=&quot;mysql&quot; charset=&quot;utf8&quot;&gt;sql/example.install.sql&lt;/file&gt;<br />
&lt;/sql&gt;<br />
&lt;/install&gt;<br />
&lt;uninstall folder=&quot;admin&quot;&gt;<br />
&lt;sql&gt;<br />
&lt;file driver=&quot;mysql&quot; charset=&quot;utf8&quot;&gt;sql/example.uninstall.sql&lt;/file&gt;<br />
&lt;/sql&gt;<br />
&lt;/uninstall&gt;<br />
&lt;/source&gt;<br />
<br />
In above example, we put sql files in &quot;admin/sql&quot; folder of installation package. You have to include &quot;sql&quot; folder in administration files.<br />
<br />
You can execute SQL during installation and/or uninstallation using the &lt;code&gt;&lt;install&gt;&lt;/code&gt; and &lt;code&gt;&lt;uninstall&gt;&lt;/code&gt; elements, respectively. An &lt;code&gt;&lt;sql&gt;&lt;/code&gt; element should appear as a child of these elements. &lt;code&gt;&lt;sql&gt;&lt;/code&gt; can contain any number of &lt;code&gt;&lt;file&gt;&lt;/code&gt; elements, each defining a single SQL file to execute. Their database driver types are described by the &lt;code&gt;driver&lt;/code&gt; attribute, their character sets by the &lt;code&gt;charset&lt;/code&gt; attribute.<br />
<br />
==== Update of the SQL schema ====<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;update&gt;<br />
&lt;schemas&gt;<br />
&lt;schemapath type=&quot;mysql&quot;&gt;sql/updates/mysql&lt;/schemapath&gt;<br />
&lt;schemapath type=&quot;sqlsrv&quot;&gt;sql/updates/sqlsrv&lt;/schemapath&gt;<br />
&lt;/schemas&gt;<br />
&lt;/update&gt;<br />
&lt;/source&gt;<br />
<br />
Since 1.6, there is also an &lt;code&gt;&lt;update&gt;&lt;/code&gt; tag, which allows to provide a series of SQL files to update the current schema.<br />
<br />
=== Language files ===<br />
In Joomla! 1.5, we put extension language files in Joomla! main language file, using &lt;languages&gt;..&lt;/languages&gt; tag as shown below. '''This tag considered to be deprecated since Joomla! 1.6.''' We encourage you to put extension 's language files in extension folder and Joomla! is responsible for loading of required language files.<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;!-- Joomla! 1.5 language tag, deprecated since Joomla! 1.6 --&gt;<br />
&lt;languages folder=&quot;langfiles&quot;&gt;<br />
&lt;language tag=&quot;en-GB&quot;&gt;en-GB.com_example.ini&lt;/language&gt;<br />
&lt;/languages&gt;<br />
&lt;/source&gt;<br />
<br />
Storing extension language files in extension folder, you gain benefit when removing some language from Joomla! installation. As your language files were not removed, when reinstall the language again you can use that files without install them again.<br />
<br />
The structure of language folder for frontend and backend is the same. You put them in &lt;language&gt; tag of your folder e.g. language/en-GB/. You have to specify these folders in front-end and back-end files too.<br />
<br />
During development you can turn on language debuggin in Joomla! global configuration. So you can investigate if the problems exists.<br />
<br />
=== Script file ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;scriptfile&gt;example.script.php&lt;/scriptfile&gt;<br />
&lt;/source&gt;<br />
<br />
An optional '''script file''' (PHP code that is run before, during and/or after installation, uninstallation and upgrading) can be defined using a &lt;code&gt;&lt;scriptfile&gt;&lt;/code&gt; element. This file should contain a class named &quot;&lt;element_name&gt;IntallerScript&quot; where &lt;element_name&gt; is the name of your extension (e.g. com_componentname, mod_modulename, etc.). Plugins requires to state the group (e.g. plgsystempluginname). The structure of the class is as follows:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
class com_componentnameInstallerScript<br />
{<br />
/**<br />
* Constructor<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*/<br />
public function __constructor(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called before any type of action<br />
*<br />
* @param string $route Which action is happening (install|uninstall|discover_install)<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function preflight($route, JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called after any type of action<br />
*<br />
* @param string $route Which action is happening (install|uninstall|discover_install)<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function postflight($route, JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on installation<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function install(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on update<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*<br />
* @return boolean True on success<br />
*/<br />
public function update(JAdapterInstance $adapter);<br />
<br />
/**<br />
* Called on uninstallation<br />
*<br />
* @param JAdapterInstance $adapter The object responsible for running this script<br />
*/<br />
public function uninstall(JAdapterInstance $adapter);<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
=== Update servers ===<br />
<br />
&lt;source lang=&quot;xml&quot;&gt;<br />
&lt;updateservers&gt;<br />
&lt;server type=&quot;extension&quot; priority=&quot;1&quot; name=&quot;Extension Update Site&quot;&gt;http://example.com/extension.xml&lt;/server&gt;<br />
&lt;server type=&quot;collection&quot; priority=&quot;2&quot; name=&quot;Collection Update Site&quot;&gt;http://example.com/collection.xml&lt;/server&gt;<br />
&lt;/updateservers&gt;<br />
&lt;/source&gt;<br />
<br />
Update servers can be defined in the &lt;code&gt;&lt;updateservers&gt;&lt;/code&gt; element, a child of the root. This element may contain one or more &lt;code&gt;&lt;server&gt;&lt;/code&gt; element, each describing a location to fetch updates from. Each &lt;code&gt;&lt;server&gt;&lt;/code&gt; item can define the following attributes:<br />
<br />
{| class=&quot;wikitable&quot;<br />
! style=&quot;width: 150px&quot; | Attribute || style=&quot;width: 150px&quot; | Values || Description<br />
|-<br />
| type || &lt;code&gt;extension&lt;/code&gt;&lt;br /&gt;&lt;code&gt;collection&lt;/code&gt; || The update server type<br />
|-<br />
| priority || ''integer'' || The priority of the update server<br />
|-<br />
| name || ''string'' || The name of the update server<br />
|}<br />
<br />
== Examples ==<br />
For a real-life example, see [http://joomlacode.org/gf/project/joomla/scmsvn/?action=browse&amp;path=%2Fdevelopment%2Ftags%2F1.6.x%2F1.6.5%2Fadministrator%2Fcomponents%2Fcom_banners%2Fbanners.xml&amp;view=markup the manifest of the Banner component in version 1.6.5].<br />
<br />
The Joomla testing process uses several extensions to test whether the installer works correctly. The latest versions of the manifests of these extensions are:<br />
<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/com_alpha/alpha.xml com_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/mod_alpha/mod_alpha.xml mod_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/plg_system_alpha/alpha.xml plg_system_alpha manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/tpl_simple/templateDetails.xml tpl_simple manifest]<br />
* [http://svn.joomla.org/project/cms/development/trunk/tests/_data/installer_packages/lng_xx-XX/xx-XX.xml lng_xx-XX manifest]<br />
<br />
== Contributors ==<br />
*[[User:akede|Alex Kempkens]]<br />
*[[User:dperaza|Daniel Peraza]]<br />
*[[User:nikosdion|Nicholas K. Dionysopoulos]]<br />
*[[User:mrs.siam|Prasit Gebsaap]]<br />
*[[User:cppl|Craig Phillips]]<br />
<br />
<br />
[[Category:Extension development]]<br />
[[Category:Specifications]]</div>Mvangeest//docs.joomla.org/Release_and_support_cycleRelease and support cycle2013-01-20T20:55:35Z<p>Mvangeest: Fixed numbering inconsistencies - please be careful when editing</p>
<hr />
<div>Joomla! is developed using a fixed release cycle. '''Every six months''', the Joomla! Project releases a new ''minor'' or ''major'' version of Joomla!. Joomla!'s version format is:<br />
:{{dablink|&lt;tt&gt;[major].[minor].[maintenance]&lt;/tt&gt;}}<br />
<br />
Each version of Joomla! is supported by the Joomla! Project for a limited amount of time. There are two classifications for support: short term support (STS) and long term support (LTS). Every '''fourth''' release will be assigned long term support.<br />
<br />
:*'''STS (short term support)''' releases are supported for '''seven months'''. Their support ends one month after the next release of Joomla is released. They are one click upgrades to the next STS or LTS version.<br />
<br />
:*'''LTS (long term support)''' releases are supported for '''twenty-seven months'''.<br />
<br />
Please note that both STS and LTS releases, once they have reached the ''GA (General Availability)'' status, are fully functional and ready to be used in production environment. The disadvantage of using STS releases is that you will need to update your installation of Joomla! every six months, while the advantage is that you will have access to new features and extensions earlier.<br />
<br />
Generally, the first STS release after an LTS release indicates the beginning of a new ''major release cycle''. This STS release introduces fundamentally new features and changes that break compatibility with the previous LTS. Two more STS releases follow (usually compatible with the first STS release), and the release cycle is finished by the release of an LTS release which finalizes the work of the three STS releases. The four releases in one cycle will usually be numbered &lt;tt&gt;[major].0&lt;/tt&gt;,&lt;tt&gt;[major].1&lt;/tt&gt; and &lt;tt&gt;[major].2&lt;/tt&gt; (STS) and &lt;tt&gt;[major].5&lt;/tt&gt; (LTS). For example, the STS release 3.0 will include breaking changes from 2.5, and 3.5 will include matured versions of the changes in 3.0, 3.1 and 3.2.<br />
<br />
Usually, there will be a migration path (an officially supported way of migrating to the next version) between two LTS releases (from &lt;tt&gt;[major].5&lt;/tt&gt; to &lt;tt&gt;[next major].5&lt;/tt&gt;) and between an LTS release and the STS releases in its major release cycle (from &lt;tt&gt;[major].2&lt;/tt&gt; to &lt;tt&gt;[major].5&lt;/tt&gt;, for example), but not necessarily to the '''following''' STS releases (from &lt;tt&gt;[major].5&lt;/tt&gt; to &lt;tt&gt;[next major].0&lt;/tt&gt;). In the case of 1.5 to 2.5 (LTS to LTS), for example, there is a migration path. Note that in the case of 2.5 to 3.0 (LTS to STS), there is also built-in migration path, since the changes aren't too incompatible.<br />
<br />
For more information, see [http://developer.joomla.org/strategy.html the official Development Strategy].<br />
<br />
The latest STS version documented on this Wiki is {{CurrentSTSVer}} (see [[:Category:Joomla! {{CurrentSTSVer|minor}}]]). The latest LTS version documented on this Wiki is {{CurrentLTSVer}} (see [[:Category:Joomla! {{CurrentLTSVer|minor}}]]).<br />
<br />
[[Category:Development]]</div>Mvangeest//docs.joomla.org/J1.5:Upgrading_1.5_from_an_existing_1.5x_versionJ1.5:Upgrading 1.5 from an existing 1.5x version2013-01-19T23:10:41Z<p>Mvangeest: /* Step 1: Download the upgrade file */ Updated download link and added link to package list</p>
<hr />
<div>__NOTOC__<br />
{{upgrade-intro}}<br />
<br />
For some basic information on patching and migrating, see [[Upgrading and Migrating FAQs]] and [[Upgrade Instructions]].<br />
<br />
You can also use a Joomla! extension to automate the process of loading version updates. See [http://extensions.joomla.org/extensions/core-enhancements/installers/9332 Update Manager for Joomla!] for more information. <br />
<br />
Review the release notes for the new version.<br />
<br />
When upgrading from a version that is not the most recent, review [http://www.joomla.org/announcements/release-news release notes for the prior releases.]<br />
<br />
==Step 1: Download the upgrade file==<br />
<br />
To download the most recent patch package and to obtain the MD5 hash:<br />
<br />
* Visit the [http://joomlacode.org/gf/project/joomla/frs/?action=index release download index].<br />
* Find the correct update file. The Joomla 1.5 downloads are located at the bottom of the page.<br />
** If you are on the version ''prior to the current one'', use the file that updates from the prior version to the current version (for example, [http://joomlacode.org/gf/download/frsrelease/16891/73387/Joomla_1.5.25_to_1.5.26-Stable-Patch_Package.zip Joomla_1.5.25_to_1.5.26-Stable-Patch_Package]).<br />
** If you are on an ''older'' version, use the 1.5.0 to current version file (for example, [http://joomlacode.org/gf/download/frsrelease/16891/73384/Joomla_1.5.0_to_1.5.26-Stable-Patch_Package.zip Joomla_1.5.0_to_1.5.26-Stable-Patch_Package]). <br />
** Select the archive format (zip, tar.gz or tar.bz2) that is most convenient for you. <br />
* Verify the download using the MD5 hash listed in the right column on the same line as the package you selected.<br />
<br />
If you have questions about these instructions, read the ''Additional Information'' below this table.<br />
<br />
'''Additional information:'''<br />
<br />
{{Ambox|image=notice|text=[[Chunk:patch|What is a patch?]]|style=width:400px}}<br />
<br />
<br />
{{Ambox|image=notice|text=[[Unpacking a package file|Which package format should I use?]]|style=width:400px}}<br />
<br />
<br />
{{Ambox|image=notice|text=[[How to determine a package checksum|How do I use the MD5 hash to check the package?]]|style=width:400px}}<br />
<br />
==Step 2: Backup your site==<br />
Before you actually upgrade, you really should make a backup of your site. Backup your existing Joomla site files and store all the files and database in case something gets messed up, you wont have any problem reverting back.<br />
<br />
All upgrades should be first tested on a copy of your site before being applied to a live site.<br />
<br />
==Step 3: Install the upgrade file==<br />
{{installing a package file}}<br />
<br />
==Step 4: Check your live site to make sure it is working correctly==<br />
Don't assume that the upgrade will work flawlessly just because the test upgrade worked. Check to make sure that nothing untoward has happened. It could be that differences between the live site and test site platforms will bring out a problem that you did not notice during testing. If you find a problem and it cannot be resolved quickly you might have to rollback the upgrade using the backup copy you created in step 2.<br />
<br />
Hopefully all will be well and you can relax. If you have any questions before, during, or after the upgrade then please ask them on the [http://forum.joomla.org/index.php/board,430.0.html Joomla! 1.5 Migrating and Upgrading Forum].<br />
<br />
Return to [[Upgrade Instructions]]<br />
<br />
[[Category:Upgrading]]</div>Mvangeest//docs.joomla.org/Supporting_SEF_URLs_in_your_componentSupporting SEF URLs in your component2012-11-25T18:17:47Z<p>Mvangeest: Added information and removed Incomplete template - this page is not complete, but contains enough information to be useful</p>
<hr />
<div>{{:Search Engine Friendly URLs}}<br />
In Joomla!, each [[component]] is responsible for handling its own SEF URLs. Therefore, as the [[Developers|developer]] of a component, you will have to create your own '''router''' to allow your component to use SEF URLs.<br />
<br />
== The Concept ==<br />
<br />
Assuming you are following standard development practices, your component is probably using &quot;system URLs&quot; that look a lot like &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;, and your goal is to transform this into &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;. As the developer, you have two tasks: signalling the system that certain pieces of text are URLs and need to be transformed, and explaining the system how to transform URLs.<br />
<br />
=== Applying &lt;code&gt;JRoute::_&lt;/code&gt; ===<br />
<br />
It is difficult and inefficient for Joomla! to figure out which parts of your component's output are URLs. To support SEF URLs, you will need to change URL-generating code so that it applies &lt;code&gt;JRoute::_&lt;/code&gt; before outputting the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
echo JRoute::_('index.php?view=article&amp;id=1&amp;catid=20');<br />
&lt;/source&gt;<br />
<br />
Notice that it is possible to leave out the parameters &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;Itemid&lt;/code&gt;. &lt;code&gt;option&lt;/code&gt; defaults to the name of the component currently being executed, and &lt;code&gt;Itemid&lt;/code&gt; defaults to the current menu item's ID.<br />
<br />
In general, you should only apply this to URLs that users and/or search engines are able to see. For example, there is no need to transform URLs used in redirects that immediately result in other redirects.<br />
<br />
If the user turns off SEF URLs in the site's settings, &lt;code&gt;JRoute::_&lt;/code&gt; will produce working non-SEF URLs without any changes to the code.<br />
<br />
=== Writing a router ===<br />
<br />
You'll also need to write a router, which is a single file with two functions that convert system URLs to and from SEF URLs. This file needs to be placed at &lt;tt&gt;/components/com_yourcomponent/router.php&lt;/tt&gt;.<br />
<br />
The first function, &lt;code&gt;[componentname]BuildRoute(&amp;$query)&lt;/code&gt;, must transform an array of URL parameters into an array of segments that will form the SEF URL. Schematically, the transformation works as follows:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; &lt;code&gt;JRoute::_&lt;/code&gt;, called by your component or any other extension<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentBuildRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal route building (for display)<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
The second function, &lt;code&gt;[componentname]ParseRoute($segments)&lt;/code&gt;, must transform an array of segments back into an array of URL parameters. Schematically:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal route parsing<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentParseRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
The two functions must cooperate in such a way that the original URL can be reconstructed. You can think of &lt;code&gt;BuildRoute&lt;/code&gt; as a form of [[wikipedia:Encoding|encoding]] and &lt;code&gt;ParseRoute&lt;/code&gt; as the corresponding decoding. When the original URL isn't properly reproduced, your component will stop working.<br />
<br />
== Preparing Your Data for Routing ==<br />
<br />
=== The Alias ===<br />
<br />
The first step is the generation of the so called alias. The alias is used in the URL instead of the title (the alias is the text you want to have in the URL). The alias has to be URI safe, which means accented UTF­8 characters are replaced by their ASCII­7 equivalents, white spaces by hyphens, etc.<br />
<br />
The alias can be defined by the user, but you should ensure that the above requirements for a URL safe alias are met. A good way to do so is to use the JTable::check() method during the save process. Have a look at this example code:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function check()<br />
{<br />
jimport( 'joomla.filter.output' );<br />
if(empty($this-&gt;alias)) {<br />
$this-&gt;alias = $this-&gt;title;<br />
}<br />
$this-&gt;alias = JFilterOutput::stringURLSafe($this-&gt;alias);<br />
<br />
/* All your other checks */<br />
return true;<br />
}<br />
&lt;/source&gt;<br />
<br />
If the alias field is empty the title will be used as alias. Then the alias will be made URLSafe using the &lt;code&gt;JFilterOutput::stringURLSafe()&lt;/code&gt; method.<br />
<br />
=== The Slug ===<br />
<br />
Continuing with the same example, the &quot;slug&quot; - &quot;1­:welcome­-to­-joomla&quot; has two parts. The first part is the article identifier (id) and the second is the alias. They are separated by a colon. These two elements were combined during the database query in the model:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$query = 'SELECT a.*, '.<br />
'CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(&quot;:&quot;, a.id, a.alias) ELSE a.id END as slug,'<br />
/*...*/;&lt;/source&gt;<br />
<br />
After this step the slug is used instead of the id.<br />
<br />
== Routing URLs ==<br />
<br />
The &lt;code&gt;JRoute::_&lt;/code&gt; method translates the internal Joomla! URL to a custom URL. &lt;tt&gt;JRoute&lt;/tt&gt; has three parameters and its prototype is:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_( $url, $xhtml = true, $ssl=null );&lt;/source&gt;<br />
<br />
Where:<br />
<br />
* &lt;code&gt;$url&lt;/code&gt; is a string containing the absolute or relative internal Joomla! URL.<br />
* &lt;code&gt;$xhtml&lt;/code&gt; is a boolean value that specifies whether or not the output should be in XHTML. This parameter is optional and if omitted defaults to true.<br />
* &lt;code&gt;$ssl&lt;/code&gt; is an integer value that specifies whether the URI should be secure. It should be set to 1 to force the URI to be secure using the global secure site URI, 0 to leave it in the same state as when it was passed, and -1 to force the URI to be unsecure using the global unsecure site URI.<br />
<br />
The most important parameter is &lt;code&gt;$url&lt;/code&gt;. A call to this method might look like:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_( 'index.php?view=article&amp;id='.$row-&gt;slug );&lt;/source&gt;<br />
<br />
&lt;code&gt;$row-­&gt;slug&lt;/code&gt; is the value that was generated in step 2 from a combination of id and title alias.<br />
<br />
Another advantage of using JRoute is that the router now handles $option (the component name) and the $Itemid (the menu item ID). The component itself doesn’t have to know its name ($option) or the active menu item ($Itemid) like it did in previous version of Joomla!.<br />
<br />
It is important that you think about the sequence of the URL parameter in this stage. This will be more clear when we have a deeper look at the router.php in the next section.<br />
<br />
The building process of JRouter is divided into two steps:<br />
<br />
* Create the application route. The application route is fully handled by JRouter and the component developer doesn’t have to do anything to make it work.<br />
* Create the component route. To create the component route, JRouter looks for the &lt;tt&gt;router.php&lt;/tt&gt; in the component directory which is responsible for building the route for the component.<br />
<br />
== The Component Router ==<br />
<br />
We will have two functions in the &lt;tt&gt;router.php&lt;/tt&gt;. One is responsible for building the URL and the other is responsible for parsing it. In the next examples, a very basic and a more advanced one, we assume that we have three views that links can point to. The first is a categories overview (&lt;code&gt;view=categories&lt;/code&gt;), the second is a single category (&lt;code&gt;view=category&lt;/code&gt;) and the third is a single article (&lt;code&gt;view=article&lt;/code&gt;).<br />
<br />
The file &lt;tt&gt;router.php&lt;/tt&gt; should be in the site area of your component. It is not used on admin/backend pages. Don't forget to add it to your XML [[Manifest files|manifest file]] in the site folder.<br />
<br />
=== A Simple Example ===<br />
<br />
This simple example will illustrate the basics of implementing a router for your component.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]BuildRoute( &amp;$query )<br />
{<br />
$segments = array();<br />
if(isset($query['view']))<br />
{<br />
$segments[] = $query['view'];<br />
unset( $query['view'] );<br />
}<br />
if(isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset( $query['id'] );<br />
};<br />
return $segments;<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
&lt;code&gt;JRouter&lt;/code&gt; passes a $query array to the &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; function. This function will add the relevant parts of the array to the $segments array in the right order and will return the properly ordered array. The content of the &lt;code&gt;$query&lt;/code&gt; array needs to be unset, otherwise &lt;code&gt;JRouter&lt;/code&gt; will add it to the URL in the form of a query string (i.e. any variables that are not handled by the router will be passed in the query string).<br />
<br />
The prefix ''componentname'' is the name for your component, as found in the directory holding the component's files. For instance, a component &quot;Magic&quot; in directory &lt;tt&gt;/components/com_magic/...&lt;/tt&gt; would use a prefix &lt;code&gt;magic&lt;/code&gt; (all lower case).<br />
<br />
The next function in the &lt;tt&gt;router.php&lt;/tt&gt; parses the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute( $segments )<br />
{<br />
$vars = array();<br />
switch($segments[0])<br />
{<br />
case 'categories':<br />
$vars['view'] = 'categories';<br />
break;<br />
case 'category':<br />
$vars['view'] = 'category';<br />
$id = explode( ':', $segments[1] );<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'article':<br />
$vars['view'] = 'article';<br />
$id = explode( ':', $segments[1] );<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
What happens here? In the function &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; we arranged the items in the &lt;code&gt;$query&lt;/code&gt; array in a specific sequence. This means that in this example the view is first and the id is second in the array.<br />
<br />
By reading &lt;code&gt;$segments[0]&lt;/code&gt;, we access the name of the view. We set the right view and/or identifier depending on its value and we return the &lt;code&gt;$vars&lt;/code&gt; array to &lt;code&gt;JRouter&lt;/code&gt;. $vars should be an associative array similar to the array that was passed to the BuildRoute method.<br />
<br />
The above example of the &lt;tt&gt;router.php&lt;/tt&gt; is a very simple way to generate sef URL's but should show how this works quite clearly.<br />
<br />
The generated URL in this example contains the name of the view and doesn't reflect the content hierarchy:<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[view]/[slug]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
=== A More Advanced Example ===<br />
<br />
In the next example we will try to get rid of the need for the view and we will try to reflect the current hierarchy level in the URL.<br />
<br />
The goal is URL's that look like:<br />
<br />
* When viewing an article: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]/[article]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing a category: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing the categories overview: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
Let's assume we have done step 1 and 2 also for the category.<br />
<br />
The link to the article would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_( 'index.php?view=article&amp;catid='.$row-­&gt;catslug .'&amp;id='.$row-­&gt;slug );<br />
&lt;/source&gt;<br />
<br />
And the Link to the category would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_( 'index.php?view=category&amp;id='.$row-&gt;catslug );<br />
&lt;/source&gt;<br />
<br />
The corresponding &lt;tt&gt;router.php&lt;/tt&gt;:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function [''Componentname'']BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if(isset( $query['catid'] ))<br />
{<br />
$segments[] = $query['catid'];<br />
unset( $query['catid'] );<br />
};<br />
if( isset($query['id']) )<br />
{<br />
$segments[] = $query['id'];<br />
unset( $query['id'] );<br />
};<br />
unset( $query['view'] );<br />
return $segments;<br />
}<br />
&lt;/source&gt;<br />
<br />
The difference now is that we don’t add the name of the view to the &lt;code&gt;$segments&lt;/code&gt; array. We still unset the view key since otherwise, &lt;code&gt;JRouter&lt;/code&gt; would add it to the URL as part of the query string. Another new thing here is the additional parameter catid that we push into the &lt;code&gt;$segments&lt;/code&gt; array.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [''Componentname'']ParseRoute($segments)<br />
{<br />
$vars = array();<br />
$app =&amp; JFactory::getApplication();<br />
$menu =&amp; $app-&gt;getMenu();<br />
$item =&amp; $menu-&gt;getActive();<br />
// Count segments<br />
$count = count( $segments );<br />
//Handle View and Identifier<br />
switch( $item-&gt;query['view'] )<br />
{<br />
case 'categories':<br />
if($count == 1) {<br />
$vars['view'] = 'category';<br />
}<br />
if($count == 2) {<br />
$vars['view'] = 'article';<br />
}<br />
$id = explode( ':', $segments[$count-1] );<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'category':<br />
$id = explode( ':', $segments[$count-1] );<br />
$vars['id'] = (int) $id[0];<br />
$vars['view'] = 'article';<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
You can see that this ParseRoute function has a lot of different code parts in comparison to the previous. The reason for this is simple. We don’t have the name of the view in the &lt;code&gt;$segments&lt;/code&gt; array and we need to find another way to determine it.<br />
<br />
We need to find out which level of hierarchy we are in by receiving the root element. We do this by looking to the view name of the active menu item:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$item-­&gt;query['view']<br />
&lt;/source&gt;<br />
<br />
Also we need to know the number of items in the &lt;code&gt;$segments&lt;/code&gt; array:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$count = count( $segments );<br />
&lt;/source&gt;<br />
<br />
With this information we can correctly set the view for all possible three cases:<br />
<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has two items (&lt;code&gt;$catid&lt;/code&gt; and &lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to an article.<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has one item (&lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to a category.<br />
* The menu item is a link to a category. In this case, we know that any item in the &lt;code&gt;$segments&lt;/code&gt; array is the identifier for an article.<br />
<br />
The result of all this code is clean and human-readable component URLs.<br />
<br />
== Routers and Menu Items ==<br />
<br />
A last important part of creating a router is considering what to do with menu items. As explained on [[Search Engine Friendly URLs]], the output of the component router is used ''after'' the first segment of a route, the first segment being the menu item's alias. This creates a difficult question: how is your router and/or other code to know which menu item to route through?<br />
<br />
Suppose, for example, that your component is currently producing output for the page &lt;tt&gt;/dogs&lt;/tt&gt;, which lists all dogs in the system. Of course, the items in the list need to be links to pages that display more details about one dog. What should the URL to the dog with ID 21 and name Fido become? Using a router that works according to the principles we've seen so far, the route that is produced is &lt;tt&gt;dogs/21-fido&lt;/tt&gt;, or with some additional work &lt;tt&gt;/dogs/fido&lt;/tt&gt;. But perhaps the user has created a menu item with the alias &lt;tt&gt;mydoggy&lt;/tt&gt; which displays exactly that dog's details. Then it is probably the user's intention to route this URL through that menu item, and the item in the list should link to the page &lt;tt&gt;/mydoggy&lt;/tt&gt;.<br />
<br />
More generally, whenever you are building a route, you will need to find the menu item that is most suitable as a ''starting point'' for building your route. The term ''starting point'' is emphasized because the rest of the route depends on the configuration of the menu item. In our example above, &lt;tt&gt;/dogs/21-fido&lt;/tt&gt; is an acceptable route, &lt;tt&gt;/mydoggy&lt;/tt&gt; is arguably even better, but &lt;tt&gt;/mydoggy/21-fido&lt;/tt&gt; is simply wrong, since &lt;tt&gt;/mydoggy&lt;/tt&gt; is in itself a menu item that is set up to display &lt;tt&gt;fido&lt;/tt&gt;'s information.<br />
<br />
Several approaches are available to tackle this problem. Joomla!'s core components take a mixed approach, separating responsibilities in two units of code: the router itself and the so-called &lt;code&gt;[componentname]RouteHelper&lt;/code&gt;. The &lt;code&gt;[componentname]RouteHelper&lt;/code&gt; provides methods that find the most suitable menu item for a given piece of data to be displayed, while the router analyzes the menu item and puts any information that is not determined by the menu item's configuration into the route. This does mean that the ''calling code'' must explicitly call the helper's method before routing (&lt;code&gt;echo JRoute::_(DogsRouteHelper::getDogRoute(21));&lt;/code&gt;).<br />
<br />
== See Also ==<br />
<br />
There is a useful thread on this subject here: [[jtopic:148632]] (note, may be out of date)<br />
<br />
For details on the internals of routing, see [[Routing implementation details]].<br />
&lt;noinclude&gt;[[Category:Tutorials]][[Category:Component Development]][[Category:Search Engine Friendly URLs]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Search_Engine_Friendly_URLsSearch Engine Friendly URLs2012-11-25T17:03:57Z<p>Mvangeest: Improved wording</p>
<hr />
<div>&lt;onlyinclude&gt;<br />
'''Search engine friendly (SEF)''', '''human-readable''' or [[wikipedia:Clean_URL|clean URLs]] are URLs that make sense to both humans and search engines because they explain the path to the particular page they point to. Since version 1.5, Joomla! is capable of creating and parsing URLs in any format, including SEF URLs. This does not depend on URL rewriting executed by the web server, so it works even if Joomla! runs a server other than Apache with the mod_rewrite module. The SEF URLs follow a certain fixed pattern, but the user can define a [[Alias|short descriptive text (alias)]] for each segment of the URL.<br />
<br />
Internally, the local part of a SEF URL (the part after the domain name) is called a '''route'''. Creating and processing SEF URLs is therefore referred to as '''routing''', and the relevant code is called a '''router'''.<br />
&lt;/onlyinclude&gt;<br />
A good example of routing is the URL to &quot;Welcome to Joomla!&quot; article in the sample data.<br />
<br />
* Without SEF URLs turned on, the URL is &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_content&amp;view=article&amp;id=1:welcome-to-joomla&amp;catid=1:latest-news&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
* With SEF URLs on and mod_rewrite off, it's &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php/the-­news/1-­latest­-news/1­-welcome­-to­-joomla&lt;/nowiki&gt;&lt;/tt&gt;<br />
* With both SEF URLs and mod_rewrite on, it's &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/the-­news/1­-latest-­news/1-­welcome-­to­-joomla&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
Search engine friendly URLs can be activated by turning on the '''Search Engine Friendly URLs''' option in the ''Global Configuration''. This option is on by default since Joomla! 1.6. See [[Enabling Search Engine Friendly (SEF) URLs]] for more information.<br />
<br />
== Frequently Asked Questions ==<br />
<br />
=== What do the numbers in the URL mean? ===<br />
By comparing the old and the new URL we can see numbers in the old URL,<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_content&amp;view=article&amp;id=1:welcome-to-joomla&amp;catid=1:latest-news&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
but also in the new URL:<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/the-­news/1­-latest-­news/1-­welcome-­to­-joomla&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
These numbers are the parameters that are needed by Joomla! to get the internal URL and show the page you want to see. (In this case, the first numeral one is the ID of the category, the second numeral one is the ID of the article.)<br />
<br />
=== There is no &lt;tt&gt;index.php&lt;/tt&gt; in the URL anymore. Can I delete the file now? ===<br />
No! The URL may doesn't contain the &lt;tt&gt;index.php&lt;/tt&gt; anymore, but internally the mod_rewrite will only redirect to the original path without showing it to you.<br />
<br />
=== What is the [[Alias]] value? And how does it get created? ===<br />
Alias is listed beneath the Title field in Articles, Categories, Sections and Menu Items. Joomla! can automatically create the alias for you. An automatic alias begins with the title. All upper case letters are changed to lower case. Spaces and special characters not allowed in a URL; they are changed to dashes.<br />
<br />
=== I want to specify my own value for Alias. ===<br />
If you do not like the alias provided by Joomla!, you can enter a value of your choosing into that field. Many believe using good keywords in your URL helps search engine optimization. You can do so by including those keywords in your title, and allowing Joomla! to create the alias, or by creating the alias yourself.<br />
<br />
=== How is Alias used in a URL? ===<br />
For a menu item, Joomla! uses the alias as the URL plug. Assume that you use the first two SEF URL options and you create a menu item called Products. Your URL would be example.com/products.<br />
<br />
Joomla! also uses the primary key values of data within the URL to help the router navigate to the correct page. Continuing with the previous example, if your products menu item was for an Article­/Category Blog, the link for the Article Title and/or Read More link would have three parts:<br />
<br />
* The menu item URL - example.com/products;<br />
<br />
* Plus, the primary key for the Category and the Category alias - 32-fruit;<br />
<br />
* Plus, the primary key for the Article and the Article alias - 1-apple;<br />
<br />
The complete URL is: &lt;tt&gt;&lt;nowiki&gt;http://example.com/products/32-fruit/1-apple&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
=== How can I get rid of the numbers in the SEF URLs? ===<br />
The numbers in the SEF URL are needed by Joomla!'s router to know how to direct site traffic. Once the router logic stabilizes, simple third party system plugins can be developed to augment the router capabilities by allowing more choice. At that time, numbers will likely be removed from the URL.<br />
<br />
== Route Formats and the Routing Mechanism ==<br />
<br />
''This section describes Joomla!'s core (built-in) routing mechanism. Routing extensions may change the way routes are created on your system.''<br />
<br />
=== Route Formats ===<br />
<br />
To describe the Joomla! routing mechanism in more detail, we first need to pin down what we refer to as a '''route'''. Suppose that Joomla! has been installed in &lt;tt&gt;&lt;nowiki&gt;http://example.com/sites/first/&lt;/nowiki&gt;&lt;/tt&gt;. The installation path is generally referred to as the '''base URL'''. A possible example URL is &lt;tt&gt;&lt;nowiki&gt;http://example.com/sites/first/products/32-fruit/1-apple&lt;/nowiki&gt;&lt;/tt&gt;. The first part of this URL is the aforementioned base URL, and neither Joomla! nor any component router can create URLs with a different first part. The second part, &lt;tt&gt;products/32-fruit/1-apple&lt;/tt&gt;, is a '''route''', consisting of three '''segment'''s.<br />
<br />
The first segment of a route is, for regular URLs, the alias of a menu item. The SEF URL is said to be '''routed through''' that menu item. The other segments are determined entirely by the router of the component that provides the type of the menu item. The ''Category - Blog'' menu item type, for example, is provided by the [[Content]] component, and therefore that component's router is responsible for building and parsing the remaining segments.<br />
<br />
It is also possible (for extensions) to ask the system to create a route without supplying a menu item to route through. In that case, the system will usually decide to create a special route that has the word &lt;tt&gt;component&lt;/tt&gt; as the first segment. These routes are created using a fixed format: the name of the component (without the leading &lt;tt&gt;com_&lt;/tt&gt;) is selected as the second segment and any parameters as the other segments.<br />
<br />
=== Limitations ===<br />
<br />
It is important to note creating a menu item is the ''only'' way for a Joomla! user to define a route that leads to a specific component. It is, however, possible to create a route without showing it on the site (in a menu). An often-applied method is to create a menu item in a menu that isn't displayed anywhere. Such a menu is usually called a [[Menu|hidden menu]].<br />
<br />
The previous paragraph implies that it is not possible to make one component responsible for handling all routes. For example, it is not possible to specify that the URL &lt;tt&gt;&lt;nowiki&gt;http://example.com/thealias&lt;/nowiki&gt;&lt;/tt&gt; should display the Content item with the alias &lt;tt&gt;thealias&lt;/tt&gt;, where &lt;tt&gt;thealias&lt;/tt&gt; could be any word. If this needs to be done for a small number of articles, menu items can be created manually for these. Else a routing extension is necessary.<br />
<br />
This routing mechanism is therefore not as flexible as users sometimes require. On the other hand, it has one large advantage: it reduces the chance of ambiguous routes (routes that could lead to two different pages). Since the first segment of a route is always a menu item alias, the system immediately knows which component's router must be used to parse it.<br />
<br />
== Implementation Details ==<br />
=== Handling Routes ===<br />
<br />
''This section describes the routing implementation. If you are a component developer, see [[Supporting SEF URLs in your component]].''<br />
<br />
Joomla routes are created and resolved by [[JRouter|the JRouter class]]. This class looks in the component root of the currently active component (specified in the &lt;code&gt;option&lt;/code&gt; parameter in the query string) and includes the &lt;tt&gt;router.php&lt;/tt&gt; file in that component's root directory. It then calls one of two functions: one for creating the SEF URL and one for interpreting the SEF URL.<br />
<br />
The JRouter class is overridden by the Joomla CMS in &lt;tt&gt;/includes/router.php&lt;/tt&gt;. In this file the build and parse functions are overridden to properly build and parse the URLs for the Joomla CMS.<br />
<br />
The &lt;tt&gt;router.php&lt;/tt&gt; file in each component (for example, &lt;tt&gt;/components/com_content/router.php&lt;/tt&gt;) should contain the following two functions:<br />
* ContentBuildRoute - this builds the SEF URL<br />
** Parameters<br />
*** $query - this is a named array containing the querystring variables<br />
** Returns: an array of segments where each segment is separated by a '/' when later combined to create the actual URL (the items in the array should not contain '/' characters)<br />
* ContentParseRoute - this interprets an SEF URL<br />
** Parameters<br />
*** $segments - this is an array that contains the segments of the URL requested.<br />
** Returns: a name =&gt; value array of the querystring variables that the link maps to<br />
<br />
=== The SEF Plugin ===<br />
The Joomla ''System - SEF'' plugin inherits &lt;code&gt;JPlugin&lt;/code&gt; and implements the &lt;code&gt;onAfterRender()&lt;/code&gt; function. In this function the body of the response that will be sent to the browser is retrieved using &lt;code&gt;JResponse::getBody()&lt;/code&gt;. The body of the response is then searched for links containing &lt;tt&gt;/index.php...&lt;/tt&gt; and replaces them with a correct SEF URL by calling &lt;code&gt;JRoute::_(''url'')&lt;/code&gt;.<br />
<br />
JRoute builds SEF URLs by instantiating a &lt;code&gt;JRouter&lt;/code&gt; object and requesting that it build the correct link from the passed in URL.<br />
<br />
=== Handling SEF URLs ===<br />
By default the SEF URLs are handled by the &lt;code&gt;JRouterSite&lt;/code&gt; object (from &lt;tt&gt;/includes/router.php&lt;/tt&gt;) and is called by a call to &lt;code&gt;JApplication::route()&lt;/code&gt; in index.php. This call is made on the &lt;code&gt;$app&lt;/code&gt; variable which is actually an instance of &lt;code&gt;JSite&lt;/code&gt; (from &lt;tt&gt;/includes/application.php&lt;/tt&gt;).<br />
<br />
&lt;code&gt;JApplication::route()&lt;/code&gt; has a non-destructive result on the &lt;code&gt;$_GET&lt;/code&gt; array. That is, &lt;code&gt;JApplication::route()&lt;/code&gt; sets variables in &lt;code&gt;$_GET&lt;/code&gt; by calling &lt;code&gt;JRequest::set()&lt;/code&gt; with the overwrite flag set to false. Thus if a variable name is returned from &lt;code&gt;JRouter::route()&lt;/code&gt; that is already in &lt;code&gt;$_GET&lt;/code&gt;, it will not put that value into &lt;code&gt;$_GET&lt;/code&gt;. This allows for custom routing.<br />
<br />
=== Custom Routing ===<br />
Joomla allows you to create your own routing mechanism. In order to create this mechanism you must have a plugin that overrides the &lt;code&gt;JPlugin::onAfterInitialise()&lt;/code&gt; function. This function then parses the URL and creates the needed variables in &lt;code&gt;$_GET&lt;/code&gt; before the standard Joomla routing is done.<br />
<br />
''See [[Creating a System Plugin to augment JRouter]] for an example.''<br />
<br />
[[Category:Search Engine Friendly URLs| ]]</div>Mvangeest//docs.joomla.org/Search_Engine_Friendly_URLsSearch Engine Friendly URLs2012-11-25T16:11:58Z<p>Mvangeest: Adjusted layout</p>
<hr />
<div>&lt;onlyinclude&gt;<br />
'''Search engine friendly (SEF)''', '''human-readable''' or [[wikipedia:Clean_URL|clean URLs]] are URLs that make sense to both humans and search engines because they explain the path to the particular page they point to. Since version 1.5, Joomla! is capable of creating and parsing URLs in any format, including SEF URLs. This does not depend on URL rewriting executed by the web server, so it works even if Joomla! runs a server other than Apache with the mod_rewrite module. The SEF URLs follow a certain fixed pattern, but the user can define a [[Alias|short descriptive text (alias)]] for each segment of the URL.<br />
<br />
Internally, the local part of a SEF URL (the part after the domain name) is called a '''route'''. Creating and processing SEF URLs is therefore referred to as '''routing''', and the relevant code is called a '''router'''.<br />
&lt;/onlyinclude&gt;<br />
A good example of routing is the URL to &quot;Welcome to Joomla!&quot; article in the sample data.<br />
<br />
* Without SEF URLs turned on, the URL is &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_content&amp;view=article&amp;id=1:welcome-to-joomla&amp;catid=1:latest-news&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
* With SEF URLs on and mod_rewrite off, it's &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php/the-­news/1-­latest­-news/1­-welcome­-to­-joomla&lt;/nowiki&gt;&lt;/tt&gt;<br />
* With both SEF URLs and mod_rewrite on, it's &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/the-­news/1­-latest-­news/1-­welcome-­to­-joomla&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
Search engine friendly URLs can be activated by turning on the '''Search Engine Friendly URLs''' option in the ''Global Configuration''. This option is on by default since Joomla! 1.6. See [[Enabling Search Engine Friendly (SEF) URLs]] for more information.<br />
<br />
== Frequently Asked Questions ==<br />
<br />
=== What do the numbers in the URL mean? ===<br />
By comparing the old and the new URL we can see numbers in the old URL,<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_content&amp;view=article&amp;id=1:welcome-to-joomla&amp;catid=1:latest-news&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
but also in the new URL:<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/the-­news/1­-latest-­news/1-­welcome-­to­-joomla&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
These numbers are the parameters that are needed by Joomla! to get the internal URL and show the page you want to see. (In this case, the first numeral one is the ID of the category, the second numeral one is the ID of the article.)<br />
<br />
=== There is no &lt;tt&gt;index.php&lt;/tt&gt; in the URL anymore. Can I delete the file now? ===<br />
No! The URL may doesn't contain the &lt;tt&gt;index.php&lt;/tt&gt; anymore, but internally the mod_rewrite will only redirect to the original path without showing it to you.<br />
<br />
=== What is the [[Alias]] value? And how does it get created? ===<br />
Alias is listed beneath the Title field in Articles, Categories, Sections and Menu Items. Joomla! can automatically create the alias for you. An automatic alias begins with the title. All upper case letters are changed to lower case. Spaces and special characters not allowed in a URL; they are changed to dashes.<br />
<br />
=== I want to specify my own value for Alias. ===<br />
If you do not like the alias provided by Joomla!, you can enter a value of your choosing into that field. Many believe using good keywords in your URL helps search engine optimization. You can do so by including those keywords in your title, and allowing Joomla! to create the alias, or by creating the alias yourself.<br />
<br />
=== How is Alias used in a URL? ===<br />
For a menu item, Joomla! uses the alias as the URL plug. Assume that you use the first two SEF URL options and you create a menu item called Products. Your URL would be example.com/products.<br />
<br />
Joomla! also uses the primary key values of data within the URL to help the router navigate to the correct page. Continuing with the previous example, if your products menu item was for an Article­/Category Blog, the link for the Article Title and/or Read More link would have three parts:<br />
<br />
* The menu item URL - example.com/products;<br />
<br />
* Plus, the primary key for the Category and the Category alias - 32-fruit;<br />
<br />
* Plus, the primary key for the Article and the Article alias - 1-apple;<br />
<br />
The complete URL is: &lt;tt&gt;&lt;nowiki&gt;http://example.com/products/32-fruit/1-apple&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
=== How can I get rid of the numbers in the SEF URLs? ===<br />
The numbers in the SEF URL are needed by Joomla!'s router to know how to direct site traffic. Once the router logic stabilizes, simple third party system plugins can be developed to augment the router capabilities by allowing more choice. At that time, numbers will likely be removed from the URL.<br />
<br />
== Route Formats and the Routing Mechanism ==<br />
<br />
''This section describes Joomla!'s core (built-in) routing mechanism. Routing extensions may change the way routes are created on your system.''<br />
<br />
=== Route Formats ===<br />
<br />
To describe the Joomla! routing mechanism in more detail, we first need to pin down what we refer to as a '''route'''. In our example URL, &lt;tt&gt;&lt;nowiki&gt;http://example.com/sites/first/products/32-fruit/1-apple&lt;/nowiki&gt;&lt;/tt&gt;, &lt;tt&gt;&lt;nowiki&gt;http://example.com/sites/first/&lt;/nowiki&gt;&lt;/tt&gt; is the part of the URL that is the same for all URLs managed by a Joomla! installation. It is generally referred to as the '''base URL'''. Neither Joomla! nor any component router can create URLs with a different first part. The second part, &lt;tt&gt;products/32-fruit/1-apple&lt;/tt&gt;, is a '''route''', consisting of three '''segment'''s.<br />
<br />
The first segment of a route is, for regular URLs, the alias of a menu item. The SEF URL is said to be '''routed through''' that menu item. The other segments are determined entirely by the router of the component that provides the type of the menu item. The ''Category - Blog'' menu item type, for example, is provided by the [[Content]] component, and therefore that component's router is responsible for building and parsing the remaining segments.<br />
<br />
It is also possible (for extensions) to ask the system to create a route without supplying a menu item to route through. In that case, the system will usually decide to create a special route that has the word &lt;tt&gt;component&lt;/tt&gt; as the first segment. These routes are created using a fixed format: the name of the component (without the leading &lt;tt&gt;com_&lt;/tt&gt;) is selected as the second segment and any parameters as the other segments.<br />
<br />
=== Limitations ===<br />
<br />
It is important to note creating a menu item is the ''only'' way for a Joomla! user to define a route that leads to a specific component. It is, however, possible to create a route without showing it on the site (in a menu). An often-applied method is to create a menu item in a menu that isn't displayed anywhere. Such a menu is usually called a [[Menu|hidden menu]].<br />
<br />
The previous paragraph implies that it is not possible to make one component responsible for handling all routes. For example, it is not possible to specify that the URL &lt;tt&gt;&lt;nowiki&gt;http://example.com/thealias&lt;/nowiki&gt;&lt;/tt&gt; should display the Content item with the alias &lt;tt&gt;thealias&lt;/tt&gt;, where &lt;tt&gt;thealias&lt;/tt&gt; could be any word. If this needs to be done for a small number of articles, menu items can be created manually for these. Else a routing extension is necessary.<br />
<br />
This routing mechanism is therefore not as flexible as users sometimes require. On the other hand, it has one large advantage: it reduces the chance of ambiguous routes (routes that could lead to two different pages). Since the first segment of a route is always a menu item alias, the system immediately knows which component's router must be used to parse it.<br />
<br />
== Implementation Details ==<br />
=== Handling Routes ===<br />
<br />
''This section describes the routing implementation. If you are a component developer, see [[Supporting SEF URLs in your component]].''<br />
<br />
Joomla routes are created and resolved by [[JRouter|the JRouter class]]. This class looks in the component root of the currently active component (specified in the &lt;code&gt;option&lt;/code&gt; parameter in the query string) and includes the &lt;tt&gt;router.php&lt;/tt&gt; file in that component's root directory. It then calls one of two functions: one for creating the SEF URL and one for interpreting the SEF URL.<br />
<br />
The JRouter class is overridden by the Joomla CMS in &lt;tt&gt;/includes/router.php&lt;/tt&gt;. In this file the build and parse functions are overridden to properly build and parse the URLs for the Joomla CMS.<br />
<br />
The &lt;tt&gt;router.php&lt;/tt&gt; file in each component (for example, &lt;tt&gt;/components/com_content/router.php&lt;/tt&gt;) should contain the following two functions:<br />
* ContentBuildRoute - this builds the SEF URL<br />
** Parameters<br />
*** $query - this is a named array containing the querystring variables<br />
** Returns: an array of segments where each segment is separated by a '/' when later combined to create the actual URL (the items in the array should not contain '/' characters)<br />
* ContentParseRoute - this interprets an SEF URL<br />
** Parameters<br />
*** $segments - this is an array that contains the segments of the URL requested.<br />
** Returns: a name =&gt; value array of the querystring variables that the link maps to<br />
<br />
=== The SEF Plugin ===<br />
The Joomla ''System - SEF'' plugin inherits &lt;code&gt;JPlugin&lt;/code&gt; and implements the &lt;code&gt;onAfterRender()&lt;/code&gt; function. In this function the body of the response that will be sent to the browser is retrieved using &lt;code&gt;JResponse::getBody()&lt;/code&gt;. The body of the response is then searched for links containing &lt;tt&gt;/index.php...&lt;/tt&gt; and replaces them with a correct SEF URL by calling &lt;code&gt;JRoute::_(''url'')&lt;/code&gt;.<br />
<br />
JRoute builds SEF URLs by instantiating a &lt;code&gt;JRouter&lt;/code&gt; object and requesting that it build the correct link from the passed in URL.<br />
<br />
=== Handling SEF URLs ===<br />
By default the SEF URLs are handled by the &lt;code&gt;JRouterSite&lt;/code&gt; object (from &lt;tt&gt;/includes/router.php&lt;/tt&gt;) and is called by a call to &lt;code&gt;JApplication::route()&lt;/code&gt; in index.php. This call is made on the &lt;code&gt;$app&lt;/code&gt; variable which is actually an instance of &lt;code&gt;JSite&lt;/code&gt; (from &lt;tt&gt;/includes/application.php&lt;/tt&gt;).<br />
<br />
&lt;code&gt;JApplication::route()&lt;/code&gt; has a non-destructive result on the &lt;code&gt;$_GET&lt;/code&gt; array. That is, &lt;code&gt;JApplication::route()&lt;/code&gt; sets variables in &lt;code&gt;$_GET&lt;/code&gt; by calling &lt;code&gt;JRequest::set()&lt;/code&gt; with the overwrite flag set to false. Thus if a variable name is returned from &lt;code&gt;JRouter::route()&lt;/code&gt; that is already in &lt;code&gt;$_GET&lt;/code&gt;, it will not put that value into &lt;code&gt;$_GET&lt;/code&gt;. This allows for custom routing.<br />
<br />
=== Custom Routing ===<br />
Joomla allows you to create your own routing mechanism. In order to create this mechanism you must have a plugin that overrides the &lt;code&gt;JPlugin::onAfterInitialise()&lt;/code&gt; function. This function then parses the URL and creates the needed variables in &lt;code&gt;$_GET&lt;/code&gt; before the standard Joomla routing is done.<br />
<br />
''See [[Creating a System Plugin to augment JRouter]] for an example.''<br />
<br />
[[Category:Search Engine Friendly URLs| ]]</div>Mvangeest//docs.joomla.org/Search_Engine_Friendly_URLsSearch Engine Friendly URLs2012-11-25T15:43:25Z<p>Mvangeest: Added information - second attempt</p>
<hr />
<div>&lt;onlyinclude&gt;<br />
'''Search engine friendly (SEF)''', '''human-readable''' or [[wikipedia:Clean_URL|clean URLs]] are URLs that make sense to both humans and search engines because they explain the path to the particular page they point to. Since version 1.5, Joomla! is capable of creating and parsing URLs in any format, including SEF URLs. This does not depend on URL rewriting executed by the web server, so it works even if Joomla! runs a server other than Apache with the mod_rewrite module. The SEF URLs follow a certain fixed pattern, but the user can define a [[Alias|short descriptive text (alias)]] for each segment of the URL.<br />
<br />
Internally, the local part of a SEF URL (the part after the domain name) is called a '''route'''. Creating and processing SEF URLs is therefore referred to as '''routing''', and the relevant code is called a '''router'''.<br />
&lt;/onlyinclude&gt;<br />
A good example of routing is the URL to &quot;Welcome to Joomla!&quot; article in the sample data.<br />
<br />
* Without SEF URLs turned on, the URL is &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_content&amp;view=article&amp;id=1:welcome-to-joomla&amp;catid=1:latest-news&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
* With SEF URLs on and mod_rewrite off, it's &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php/the-­news/1-­latest­-news/1­-welcome­-to­-joomla&lt;/nowiki&gt;&lt;/tt&gt;<br />
* With both SEF URLs and mod_rewrite on, it's &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/the-­news/1­-latest-­news/1-­welcome-­to­-joomla&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
Search engine friendly URLs can be activated by turning on the '''Search Engine Friendly URLs''' option in the ''Global Configuration''. This option is on by default since Joomla! 1.6. See [[Enabling Search Engine Friendly (SEF) URLs]] for more information.<br />
<br />
== Frequently Asked Questions ==<br />
<br />
=== What do the numbers in the URL mean? ===<br />
By comparing the old and the new URL we can see numbers in the old URL,<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_content&amp;view=article&amp;id=1:welcome-to-joomla&amp;catid=1:latest-news&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
but also in the new URL:<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/the-­news/1­-latest-­news/1-­welcome-­to­-joomla&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
These numbers are the parameters that are needed by Joomla! to get the internal URL and show the page you want to see. (In this case, the first numeral one is the ID of the category, the second numeral one is the ID of the article.)<br />
<br />
=== There is no &lt;tt&gt;index.php&lt;/tt&gt; in the URL anymore. Can I delete the file now? ===<br />
No! The URL may doesn't contain the &lt;tt&gt;index.php&lt;/tt&gt; anymore, but internally the mod_rewrite will only redirect to the original path without showing it to you.<br />
<br />
=== What is the [[Alias]] value? And how does it get created? ===<br />
Alias is listed beneath the Title field in Articles, Categories, Sections and Menu Items. Joomla! can automatically create the alias for you. An automatic alias begins with the title. All upper case letters are changed to lower case. Spaces and special characters not allowed in a URL; they are changed to dashes.<br />
<br />
=== I want to specify my own value for Alias. ===<br />
If you do not like the alias provided by Joomla!, you can enter a value of your choosing into that field. Many believe using good keywords in your URL helps search engine optimization. You can do so by including those keywords in your title, and allowing Joomla! to create the alias, or by creating the alias yourself.<br />
<br />
=== How is Alias used in a URL? ===<br />
For a menu item, Joomla! uses the alias as the URL plug. Assume that you use the first two SEF URL options and you create a menu item called Products. Your URL would be example.com/products.<br />
<br />
Joomla! also uses the primary key values of data within the URL to help the router navigate to the correct page. Continuing with the previous example, if your products menu item was for an Article­/Category Blog, the link for the Article Title and/or Read More link would have three parts:<br />
<br />
* The menu item URL - example.com/products;<br />
<br />
* Plus, the primary key for the Category and the Category alias - 32-fruit;<br />
<br />
* Plus, the primary key for the Article and the Article alias - 1-apple;<br />
<br />
The complete URL is: &lt;tt&gt;&lt;nowiki&gt;http://example.com/products/32-fruit/1-apple&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
=== How can I get rid of the numbers in the SEF URLs? ===<br />
The numbers in the SEF URL are needed by Joomla!'s router to know how to direct site traffic. Once the router logic stabilizes, simple third party system plugins can be developed to augment the router capabilities by allowing more choice. At that time, numbers will likely be removed from the URL.<br />
<br />
== Route Formats and the Routing Mechanism ==<br />
<br />
''This section describes Joomla!'s core (built-in) routing mechanism. Routing extensions may change the way routes are created on your system.''<br />
<br />
To describe the Joomla! routing mechanism in more detail, we first need to pin down what we refer to as a '''route'''. In our example URL, &lt;tt&gt;&lt;nowiki&gt;http://example.com/sites/first/products/32-fruit/1-apple&lt;/nowiki&gt;&lt;/tt&gt;, &lt;tt&gt;&lt;nowiki&gt;http://example.com/sites/first/&lt;/nowiki&gt;&lt;/tt&gt; is the part of the URL that is the same for all URLs managed by a Joomla! installation. It is generally referred to as the '''base URL'''. Neither Joomla! nor any component router can create URLs with a different first part. The second part, &lt;tt&gt;products/32-fruit/1-apple&lt;/tt&gt;, is a '''route''', consisting of three '''segment'''s.<br />
<br />
The first segment of a route is, for regular URLs, the alias of a menu item. The SEF URL is said to be '''routed through''' that menu item. The other segments are determined entirely by the router of the component that provides the type of the menu item. The ''Category - Blog'' menu item type, for example, is provided by the [[Content]] component, and therefore that component's router is responsible for building and parsing the remaining segments.<br />
<br />
It is also possible (for extensions) to ask the system to create a route without supplying a menu item to route through. In that case, the system will usually decide to create a special route that has the word &lt;tt&gt;component&lt;/tt&gt; as the first segment. These routes are created using a fixed format: the name of the component (without the leading &lt;tt&gt;com_&lt;/tt&gt;) is selected as the second segment and any parameters as the other segments.<br />
<br />
It is important to note creating a menu item is the ''only'' way for a Joomla! user to define a route that leads to a specific component. It is, however, possible to create a route without showing it on the site (in a menu). An often-applied method is to create a menu item in a menu that isn't displayed anywhere. Such a menu is usually called a [[Menu|hidden menu]].<br />
<br />
The previous paragraph implies that it is not possible to make one component responsible for handling all routes. For example, it is not possible to specify that the URL &lt;tt&gt;&lt;nowiki&gt;http://example.com/thealias&lt;/nowiki&gt;&lt;/tt&gt; should display the Content item with the alias &lt;tt&gt;thealias&lt;/tt&gt;, where &lt;tt&gt;thealias&lt;/tt&gt; could be any word. If this needs to be done for a small number of articles, menu items can be created manually for these. Else a routing extension is necessary.<br />
<br />
This routing mechanism is therefore not as flexible as users sometimes require. On the other hand, it has one large advantage: it reduces the chance of ambiguous routes (routes that could lead to two different pages). Since the first segment of a route is always a menu item alias, the system immediately knows which component's router must be used to parse it.<br />
<br />
== Implementation Details ==<br />
=== Joomla Routes ===<br />
<br />
''This section describes the routing implementation. If you are a component developer, see [[Supporting SEF URLs in your component]].''<br />
<br />
Joomla routes are created and resolved by [[JRouter|the JRouter class]]. This class looks in the component root of the currently active component (specified in the &lt;code&gt;option&lt;/code&gt; parameter in the query string) and includes the &lt;tt&gt;router.php&lt;/tt&gt; file in that component's root directory. It then calls one of two functions: one for creating the SEF URL and one for interpreting the SEF URL.<br />
<br />
The JRouter class is overridden by the Joomla CMS in &lt;tt&gt;/includes/router.php&lt;/tt&gt;. In this file the build and parse functions are overridden to properly build and parse the URLs for the Joomla CMS.<br />
<br />
The &lt;tt&gt;router.php&lt;/tt&gt; file in each component (for example, &lt;tt&gt;/components/com_content/router.php&lt;/tt&gt;) should contain the following two functions:<br />
* ContentBuildRoute - this builds the SEF URL<br />
** Parameters<br />
*** $query - this is a named array containing the querystring variables<br />
** Returns: an array of segments where each segment is separated by a '/' when later combined to create the actual URL (the items in the array should not contain '/' characters)<br />
* ContentParseRoute - this interprets an SEF URL<br />
** Parameters<br />
*** $segments - this is an array that contains the segments of the URL requested.<br />
** Returns: a name =&gt; value array of the querystring variables that the link maps to<br />
<br />
=== The SEF Plugin ===<br />
The Joomla ''System - SEF'' plugin inherits &lt;code&gt;JPlugin&lt;/code&gt; and implements the &lt;code&gt;onAfterRender()&lt;/code&gt; function. In this function the body of the response that will be sent to the browser is retrieved using &lt;code&gt;JResponse::getBody()&lt;/code&gt;. The body of the response is then searched for links containing &lt;tt&gt;/index.php...&lt;/tt&gt; and replaces them with a correct SEF URL by calling &lt;code&gt;JRoute::_(''url'')&lt;/code&gt;.<br />
<br />
JRoute builds SEF URLs by instantiating a &lt;code&gt;JRouter&lt;/code&gt; object and requesting that it build the correct link from the passed in URL.<br />
<br />
=== Handling SEF URLs ===<br />
By default the SEF URLs are handled by the &lt;code&gt;JRouterSite&lt;/code&gt; object (from &lt;tt&gt;/includes/router.php&lt;/tt&gt;) and is called by a call to &lt;code&gt;JApplication::route()&lt;/code&gt; in index.php. This call is made on the &lt;code&gt;$app&lt;/code&gt; variable which is actually an instance of &lt;code&gt;JSite&lt;/code&gt; (from &lt;tt&gt;/includes/application.php&lt;/tt&gt;).<br />
<br />
&lt;code&gt;JApplication::route()&lt;/code&gt; has a non-destructive result on the &lt;code&gt;$_GET&lt;/code&gt; array. That is, &lt;code&gt;JApplication::route()&lt;/code&gt; sets variables in &lt;code&gt;$_GET&lt;/code&gt; by calling &lt;code&gt;JRequest::set()&lt;/code&gt; with the overwrite flag set to false. Thus if a variable name is returned from &lt;code&gt;JRouter::route()&lt;/code&gt; that is already in &lt;code&gt;$_GET&lt;/code&gt;, it will not put that value into &lt;code&gt;$_GET&lt;/code&gt;. This allows for custom routing.<br />
<br />
=== Custom Routing ===<br />
Joomla allows you to create your own routing mechanism. In order to create this mechanism you must have a plugin that overrides the &lt;code&gt;JPlugin::onAfterInitialise()&lt;/code&gt; function. This function then parses the URL and creates the needed variables in &lt;code&gt;$_GET&lt;/code&gt; before the standard Joomla routing is done.<br />
<br />
''See [[Creating a System Plugin to augment JRouter]] for an example.''<br />
<br />
[[Category:Search Engine Friendly URLs| ]]</div>Mvangeest//docs.joomla.org/Supporting_SEF_URLs_in_your_componentSupporting SEF URLs in your component2012-11-25T00:55:35Z<p>Mvangeest: Split off parts to Routing implementation details</p>
<hr />
<div>{{incomplete}}<br />
{{:Search Engine Friendly URLs}}<br />
In Joomla!, each [[component]] is responsible for handling its own SEF URLs. Therefore, as the [[Developers|developer]] of a component, you will have to create your own '''router''' to allow your component to use SEF URLs.<br />
<br />
== The Concept ==<br />
<br />
Assuming you are following standard development practices, your component is probably using &quot;system URLs&quot; that look a lot like &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;, and your goal is to transform this into &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;. As the developer, you have two tasks: signalling the system that certain pieces of text are URLs and need to be transformed, and explaining the system how to transform URLs.<br />
<br />
=== Applying &lt;code&gt;JRoute::_&lt;/code&gt; ===<br />
<br />
It is difficult and inefficient for Joomla! to figure out which parts of your component's output are URLs. To support SEF URLs, you will need to change URL-generating code so that it applies &lt;code&gt;JRoute::_&lt;/code&gt; before outputting the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
echo JRoute::_('index.php?view=article&amp;id=1&amp;catid=20');<br />
&lt;/source&gt;<br />
<br />
Notice that it is possible to leave out the parameters &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;Itemid&lt;/code&gt;. &lt;code&gt;option&lt;/code&gt; defaults to the name of the component currently being executed, and &lt;code&gt;Itemid&lt;/code&gt; defaults to the current menu item's ID.<br />
<br />
In general, you should only apply this to URLs that users and/or search engines are able to see. For example, there is no need to transform URLs used in redirects that immediately result in other redirects.<br />
<br />
If the user turns off SEF URLs in the site's settings, &lt;code&gt;JRoute::_&lt;/code&gt; will produce working non-SEF URLs without any changes to the code.<br />
<br />
=== Writing a router ===<br />
<br />
You'll also need to write a router, which is a single file with two functions that convert system URLs to and from SEF URLs. This file needs to be placed at &lt;tt&gt;/components/com_yourcomponent/router.php&lt;/tt&gt;.<br />
<br />
The first function, &lt;code&gt;[componentname]BuildRoute(&amp;$query)&lt;/code&gt;, must transform an array of URL parameters into an array of segments that will form the SEF URL. Schematically, the transformation works as follows:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; &lt;code&gt;JRoute::_&lt;/code&gt;, called by your component or any other extension<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentBuildRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal routing (for display)<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
The second function, &lt;code&gt;[componentname]ParseRoute($segments)&lt;/code&gt;, must transform an array of segments back into an array of URL parameters. Schematically:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal routing<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentParseRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
The two functions must cooperate in such a way that the original URL can be reconstructed. You can think of &lt;code&gt;BuildRoute&lt;/code&gt; as a form of [[wikipedia:Encoding|encoding]] and &lt;code&gt;ParseRoute&lt;/code&gt; as the corresponding decoding. When the original URL isn't properly reproduced, your component will stop working.<br />
<br />
== Preparing Your Data for Routing ==<br />
<br />
=== The Alias ===<br />
<br />
The first step is the generation of the so called alias. The alias is used in the URL instead of the title (the alias is the text you want to have in the URL). The alias has to be URI safe, which means accented UTF­8 characters are replaced by their ASCII­7 equivalents, white spaces by hyphens, etc.<br />
<br />
The alias can be defined by the user, but you should ensure that the above requirements for a URL safe alias are met. A good way to do so is to use the JTable::check() method during the save process. Have a look at this example code:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function check()<br />
{<br />
jimport( 'joomla.filter.output' );<br />
if(empty($this-&gt;alias)) {<br />
$this-&gt;alias = $this-&gt;title;<br />
}<br />
$this-&gt;alias = JFilterOutput::stringURLSafe($this-&gt;alias);<br />
<br />
/* All your other checks */<br />
return true;<br />
}<br />
&lt;/source&gt;<br />
<br />
If the alias field is empty the title will be used as alias. Then the alias will be made URLSafe using the &lt;code&gt;JFilterOutput::stringURLSafe()&lt;/code&gt; method.<br />
<br />
=== The Slug ===<br />
<br />
Continuing with the same example, the &quot;slug&quot; - &quot;1­:welcome­-to­-joomla&quot; has two parts. The first part is the article identifier (id) and the second is the alias. They are separated by a colon. These two elements were combined during the database query in the model:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$query = 'SELECT a.*, '.<br />
'CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(&quot;:&quot;, a.id, a.alias) ELSE a.id END as slug,'<br />
/*...*/;&lt;/source&gt;<br />
<br />
After this step the slug is used instead of the id.<br />
<br />
== Routing URLs ==<br />
<br />
The &lt;code&gt;JRoute::_&lt;/code&gt; method translates the internal Joomla! URL to a custom URL. &lt;tt&gt;JRoute&lt;/tt&gt; has three parameters and its prototype is:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_( $url, $xhtml = true, $ssl=null );&lt;/source&gt;<br />
<br />
Where:<br />
<br />
* &lt;code&gt;$url&lt;/code&gt; is a string containing the absolute or relative internal Joomla! URL.<br />
* &lt;code&gt;$xhtml&lt;/code&gt; is a boolean value that specifies whether or not the output should be in XHTML. This parameter is optional and if omitted defaults to true.<br />
* &lt;code&gt;$ssl&lt;/code&gt; is an integer value that specifies whether the URI should be secure. It should be set to 1 to force the URI to be secure using the global secure site URI, 0 to leave it in the same state as when it was passed, and -1 to force the URI to be unsecure using the global unsecure site URI.<br />
<br />
The most important parameter is &lt;code&gt;$url&lt;/code&gt;. A call to this method might look like:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_( 'index.php?view=article&amp;id='.$row-&gt;slug );&lt;/source&gt;<br />
<br />
&lt;code&gt;$row-­&gt;slug&lt;/code&gt; is the value that was generated in step 2 from a combination of id and title alias.<br />
<br />
Another advantage of using JRoute is that the router now handles $option (the component name) and the $Itemid (the menu item ID). The component itself doesn’t have to know its name ($option) or the active menu item ($Itemid) like it did in previous version of Joomla!.<br />
<br />
It is important that you think about the sequence of the URL parameter in this stage. This will be more clear when we have a deeper look at the router.php in the next section.<br />
<br />
The building process of JRouter is divided into two steps:<br />
<br />
* Create the application route. The application route is fully handled by JRouter and the component developer doesn’t have to do anything to make it work.<br />
* Create the component route. To create the component route, JRouter looks for the &lt;tt&gt;router.php&lt;/tt&gt; in the component directory which is responsible for building the route for the component.<br />
<br />
== The Component Router ==<br />
<br />
We will have two functions in the &lt;tt&gt;router.php&lt;/tt&gt;. One is responsible for building the URL and the other is responsible for parsing it. In the next examples, a very basic and a more advanced one, we assume that we have three views that links can point to. The first is a categories overview (&lt;code&gt;view=categories&lt;/code&gt;), the second is a single category (&lt;code&gt;view=category&lt;/code&gt;) and the third is a single article (&lt;code&gt;view=article&lt;/code&gt;).<br />
<br />
The file &lt;tt&gt;router.php&lt;/tt&gt; should be in the site area of your component. It is not used on admin/backend pages. Don't forget to add it to your XML [[Manifest files|manifest file]] in the site folder.<br />
<br />
=== A Simple Example ===<br />
<br />
This simple example will illustrate the basics of implementing a router for your component.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]BuildRoute( &amp;$query )<br />
{<br />
$segments = array();<br />
if(isset($query['view']))<br />
{<br />
$segments[] = $query['view'];<br />
unset( $query['view'] );<br />
}<br />
if(isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset( $query['id'] );<br />
};<br />
return $segments;<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
&lt;code&gt;JRouter&lt;/code&gt; passes a $query array to the &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; function. This function will add the relevant parts of the array to the $segments array in the right order and will return the properly ordered array. The content of the &lt;code&gt;$query&lt;/code&gt; array needs to be unset, otherwise &lt;code&gt;JRouter&lt;/code&gt; will add it to the URL in the form of a query string (i.e. any variables that are not handled by the router will be passed in the query string).<br />
<br />
The prefix ''componentname'' is the name for your component, as found in the directory holding the component's files. For instance, a component &quot;Magic&quot; in directory &lt;tt&gt;/components/com_magic/...&lt;/tt&gt; would use a prefix &lt;code&gt;magic&lt;/code&gt; (all lower case).<br />
<br />
The next function in the &lt;tt&gt;router.php&lt;/tt&gt; parses the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute( $segments )<br />
{<br />
$vars = array();<br />
switch($segments[0])<br />
{<br />
case 'categories':<br />
$vars['view'] = 'categories';<br />
break;<br />
case 'category':<br />
$vars['view'] = 'category';<br />
$id = explode( ':', $segments[1] );<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'article':<br />
$vars['view'] = 'article';<br />
$id = explode( ':', $segments[1] );<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
What happens here? In the function &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; we arranged the items in the &lt;code&gt;$query&lt;/code&gt; array in a specific sequence. This means that in this example the view is first and the id is second in the array.<br />
<br />
By reading &lt;code&gt;$segments[0]&lt;/code&gt;, we access the name of the view. We set the right view and/or identifier depending on its value and we return the &lt;code&gt;$vars&lt;/code&gt; array to &lt;code&gt;JRouter&lt;/code&gt;. $vars should be an associative array similar to the array that was passed to the BuildRoute method.<br />
<br />
The above example of the &lt;tt&gt;router.php&lt;/tt&gt; is a very simple way to generate sef URL's but should show how this works quite clearly.<br />
<br />
The generated URL in this example contains the name of the view and doesn't reflect the content hierarchy:<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[view]/[slug]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
=== A More Advanced Example ===<br />
<br />
In the next example we will try to get rid of the need for the view and we will try to reflect the current hierarchy level in the URL.<br />
<br />
The goal is URL's that look like:<br />
<br />
* When viewing an article: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]/[article]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing a category: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing the categories overview: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
Let's assume we have done step 1 and 2 also for the category.<br />
<br />
The link to the article would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_( 'index.php?view=article&amp;catid='.$row-­&gt;catslug .'&amp;id='.$row-­&gt;slug );<br />
&lt;/source&gt;<br />
<br />
And the Link to the category would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_( 'index.php?view=category&amp;id='.$row-&gt;catslug );<br />
&lt;/source&gt;<br />
<br />
The corresponding &lt;tt&gt;router.php&lt;/tt&gt;:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function [''Componentname'']BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if(isset( $query['catid'] ))<br />
{<br />
$segments[] = $query['catid'];<br />
unset( $query['catid'] );<br />
};<br />
if( isset($query['id']) )<br />
{<br />
$segments[] = $query['id'];<br />
unset( $query['id'] );<br />
};<br />
unset( $query['view'] );<br />
return $segments;<br />
}<br />
&lt;/source&gt;<br />
<br />
The difference now is that we don’t add the name of the view to the &lt;code&gt;$segments&lt;/code&gt; array. We still unset the view key since otherwise, &lt;code&gt;JRouter&lt;/code&gt; would add it to the URL as part of the query string. Another new thing here is the additional parameter catid that we push into the &lt;code&gt;$segments&lt;/code&gt; array.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [''Componentname'']ParseRoute($segments)<br />
{<br />
$vars = array();<br />
$app =&amp; JFactory::getApplication();<br />
$menu =&amp; $app-&gt;getMenu();<br />
$item =&amp; $menu-&gt;getActive();<br />
// Count segments<br />
$count = count( $segments );<br />
//Handle View and Identifier<br />
switch( $item-&gt;query['view'] )<br />
{<br />
case 'categories':<br />
if($count == 1) {<br />
$vars['view'] = 'category';<br />
}<br />
if($count == 2) {<br />
$vars['view'] = 'article';<br />
}<br />
$id = explode( ':', $segments[$count-1] );<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'category':<br />
$id = explode( ':', $segments[$count-1] );<br />
$vars['id'] = (int) $id[0];<br />
$vars['view'] = 'article';<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
You can see that this ParseRoute function has a lot of different code parts in comparison to the previous. The reason for this is simple. We don’t have the name of the view in the &lt;code&gt;$segments&lt;/code&gt; array and we need to find another way to determine it.<br />
<br />
We need to find out which level of hierarchy we are in by receiving the root element. We do this by looking to the view name of the active menu item:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$item-­&gt;query['view']<br />
&lt;/source&gt;<br />
<br />
Also we need to know the number of items in the &lt;code&gt;$segments&lt;/code&gt; array:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$count = count( $segments );<br />
&lt;/source&gt;<br />
<br />
With this information we can correctly set the view for all possible three cases:<br />
<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has two items (&lt;code&gt;$catid&lt;/code&gt; and &lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to an article.<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has one item (&lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to a category.<br />
* The menu item is a link to a category. In this case, we know that any item in the &lt;code&gt;$segments&lt;/code&gt; array is the identifier for an article.<br />
<br />
The result of all this code is clean and human-readable component URLs.<br />
<br />
== See Also ==<br />
<br />
There is a useful thread on this subject here: [[jtopic:148632]] (note, may be out of date)<br />
<br />
For details on the internals of routing, see [[Routing implementation details]].<br />
&lt;noinclude&gt;[[Category:Tutorials]][[Category:Component Development]][[Category:Search Engine Friendly URLs]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Routing_implementation_detailsRouting implementation details2012-11-25T00:53:43Z<p>Mvangeest: Split off page from http://docs.joomla.org/index.php?title=Supporting_SEF_URLs_in_your_component&amp;oldid=9893 (5 August 2008)</p>
<hr />
<div>{{incomplete}}<br />
<br />
== Application Route Parsing ==<br />
<br />
The [[Application execution order]] outlines that the route (URL) is parsed immediately after initialisation is complete. Since fancy URL's are not treated (yet) in the Administrator, we will follow the route parsing process in detail when &lt;code&gt;JSite::route&lt;/code&gt; in the &lt;tt&gt;index.php&lt;/tt&gt; file.<br />
<br />
* Call to &lt;code&gt;JApplication::route&lt;/code&gt;<br />
** Clone the URI<br />
** Call to &lt;code&gt;JApplication::getRouter&lt;/code&gt;<br />
*** Call to &lt;code&gt;JRouter::getInstance&lt;/code&gt; passing the type (&quot;site&quot;)<br />
** Call to &lt;code&gt;JRouterSite::parse&lt;/code&gt; passing the URI<br />
*** Strip the suffix if applicable (added to $vars['format'])<br />
*** Re-set the route (URI)<br />
*** Call to &lt;code&gt;JRouter::parse&lt;/code&gt; passing the URI<br />
**** Call to &lt;code&gt;JRouterSite::_processParseRules&lt;/code&gt; passing the URI (this will call custom route rules)<br />
***** Call to &lt;code&gt;JRouter::_processParseRules&lt;/code&gt; passing the URI<br />
****** Call any custom routing rules (probably added via a system plugin using the &lt;code&gt;onAfterInitialise&lt;/code&gt; event trigger) passing the URI<br />
****** Returns an array of vars<br />
***** If SEF mode, replace &lt;code&gt;start&lt;/code&gt; variable with &lt;/code&gt;limitstart&lt;/code&gt;<br />
**** If raw mode, call to &lt;code&gt;JRouterSite::_parseRawRoute&lt;/code&gt; passing the URI<br />
**** If SEF mode, call to &lt;code&gt;JRouterSite::_parseSefRoute&lt;/code&gt; passing the URI<br />
***** If the route (the URI path) is empty, load it from the default menu item; set the active menu item as the default<br />
***** If first part is &lt;code&gt;/component/com_content&lt;/code&gt;, set the &lt;code&gt;option&lt;/code&gt; as the second segement. Null the &lt;code&gt;Itemid&lt;/code&gt;.<br />
***** Else, loop through menu alias values and take off segments that match as the menu tree is traversed. Set &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;Itemid&lt;/code&gt; based on the last menu item found.<br />
***** If the &lt;code&gt;Itemid&lt;/code&gt; is set in the URL, set the active menu item based on this value.<br />
***** Push the vars collected so far (eg, &lt;code&gt;option&lt;/code&gt;, &lt;code&gt;Itemid&lt;/code&gt;, etc) into the router object (&lt;code&gt;$this&lt;/code&gt;).<br />
***** If the route and &lt;code&gt;option&lt;/code&gt; is set, load the component router;<br />
***** Else, get the active menu item and get the route vars from it<br />
<br />
<br />
== Application Route Building ==<br />
<br />
TODO<br />
<br />
== Custom Router Rules ==<br />
<br />
TODO</div>Mvangeest//docs.joomla.org/Supporting_SEF_URLs_in_your_componentSupporting SEF URLs in your component2012-11-24T17:51:30Z<p>Mvangeest: Adjusted layout</p>
<hr />
<div>{{incomplete}}<br />
{{:Search Engine Friendly URLs}}<br />
In Joomla!, each [[component]] is responsible for handling its own SEF URLs. Therefore, as the [[Developers|developer]] of a component, you will have to create your own '''router''' to allow your component to use SEF URLs.<br />
<br />
== The Concept ==<br />
<br />
Assuming you are following standard development practices, your component is probably using &quot;system URLs&quot; that look a lot like &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;, and your goal is to transform this into &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;. As the developer, you have two tasks: signalling the system that certain pieces of text are URLs and need to be transformed, and explaining the system how to transform URLs.<br />
<br />
=== Applying &lt;code&gt;JRoute::_&lt;/code&gt; ===<br />
<br />
It is difficult and inefficient for Joomla! to figure out which parts of your component's output are URLs. To support SEF URLs, you will need to change URL-generating code so that it applies &lt;code&gt;JRoute::_&lt;/code&gt; before outputting the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
echo JRoute::_('index.php?view=article&amp;id=1&amp;catid=20');<br />
&lt;/source&gt;<br />
<br />
Notice that it is possible to leave out the parameters &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;Itemid&lt;/code&gt;. &lt;code&gt;option&lt;/code&gt; defaults to the name of the component currently being executed, and &lt;code&gt;Itemid&lt;/code&gt; defaults to the current menu item's ID.<br />
<br />
In general, you should only apply this to URLs that users and/or search engines are able to see. For example, there is no need to transform URLs used in redirects that immediately result in other redirects.<br />
<br />
If the user turns off SEF URLs in the site's settings, &lt;code&gt;JRoute::_&lt;/code&gt; will produce working non-SEF URLs without any changes to the code.<br />
<br />
=== Writing a router ===<br />
<br />
You'll also need to write a router, which is a single file with two functions that convert system URLs to and from SEF URLs. This file needs to be placed at &lt;tt&gt;/components/com_yourcomponent/router.php&lt;/tt&gt;.<br />
<br />
The first function, &lt;code&gt;[componentname]BuildRoute(&amp;$query)&lt;/code&gt;, must transform an array of URL parameters into an array of segments that will form the SEF URL. Schematically, the transformation works as follows:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; &lt;code&gt;JRoute::_&lt;/code&gt;, called by your component or any other extension<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentBuildRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal routing (for display)<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
The second function, &lt;code&gt;[componentname]ParseRoute($segments)&lt;/code&gt;, must transform an array of segments back into an array of URL parameters. Schematically:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal routing<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentParseRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
The two functions must cooperate in such a way that the original URL can be reconstructed. You can think of &lt;code&gt;BuildRoute&lt;/code&gt; as a form of [[wikipedia:Encoding|encoding]] and &lt;code&gt;ParseRoute&lt;/code&gt; as the corresponding decoding. When the original URL isn't properly reproduced, your component will stop working.<br />
<br />
== Preparing Your Data for Routing ==<br />
<br />
=== The Alias ===<br />
<br />
The first step is the generation of the so called alias. The alias is used in the URL instead of the title (the alias is the text you want to have in the URL). The alias has to be URI safe, which means accented UTF­8 characters are replaced by their ASCII­7 equivalents, white spaces by hyphens, etc.<br />
<br />
The alias can be defined by the user, but you should ensure that the above requirements for a URL safe alias are met. A good way to do so is to use the JTable::check() method during the save process. Have a look at this example code:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function check()<br />
{<br />
jimport( 'joomla.filter.output' );<br />
if(empty($this-&gt;alias)) {<br />
$this-&gt;alias = $this-&gt;title;<br />
}<br />
$this-&gt;alias = JFilterOutput::stringURLSafe($this-&gt;alias);<br />
<br />
/* All your other checks */<br />
return true;<br />
}<br />
&lt;/source&gt;<br />
<br />
If the alias field is empty the title will be used as alias. Then the alias will be made URLSafe using the &lt;code&gt;JFilterOutput::stringURLSafe()&lt;/code&gt; method.<br />
<br />
=== The Slug ===<br />
<br />
Continuing with the same example, the &quot;slug&quot; - &quot;1­:welcome­-to­-joomla&quot; has two parts. The first part is the article identifier (id) and the second is the alias. They are separated by a colon. These two elements were combined during the database query in the model:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$query = 'SELECT a.*, '.<br />
'CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(&quot;:&quot;, a.id, a.alias) ELSE a.id END as slug,'<br />
/*...*/;&lt;/source&gt;<br />
<br />
After this step the slug is used instead of the id.<br />
<br />
== Routing URLs ==<br />
<br />
The &lt;code&gt;JRoute::_&lt;/code&gt; method translates the internal Joomla! URL to a custom URL. &lt;tt&gt;JRoute&lt;/tt&gt; has three parameters and its prototype is:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_( $url, $xhtml = true, $ssl=null );&lt;/source&gt;<br />
<br />
Where:<br />
<br />
* &lt;code&gt;$url&lt;/code&gt; is a string containing the absolute or relative internal Joomla! URL.<br />
* &lt;code&gt;$xhtml&lt;/code&gt; is a boolean value that specifies whether or not the output should be in XHTML. This parameter is optional and if omitted defaults to true.<br />
* &lt;code&gt;$ssl&lt;/code&gt; is an integer value that specifies whether the URI should be secure. It should be set to 1 to force the URI to be secure using the global secure site URI, 0 to leave it in the same state as when it was passed, and -1 to force the URI to be unsecure using the global unsecure site URI.<br />
<br />
The most important parameter is &lt;code&gt;$url&lt;/code&gt;. A call to this method might look like:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_( 'index.php?view=article&amp;id='.$row-&gt;slug );&lt;/source&gt;<br />
<br />
&lt;code&gt;$row-­&gt;slug&lt;/code&gt; is the value that was generated in step 2 from a combination of id and title alias.<br />
<br />
Another advantage of using JRoute is that the router now handles $option (the component name) and the $Itemid (the menu item ID). The component itself doesn’t have to know its name ($option) or the active menu item ($Itemid) like it did in previous version of Joomla!.<br />
<br />
It is important that you think about the sequence of the URL parameter in this stage. This will be more clear when we have a deeper look at the router.php in the next section.<br />
<br />
The building process of JRouter is divided into two steps:<br />
<br />
* Create the application route. The application route is fully handled by JRouter and the component developer doesn’t have to do anything to make it work.<br />
* Create the component route. To create the component route, JRouter looks for the &lt;tt&gt;router.php&lt;/tt&gt; in the component directory which is responsible for building the route for the component.<br />
<br />
== The Component Router ==<br />
<br />
We will have two functions in the &lt;tt&gt;router.php&lt;/tt&gt;. One is responsible for building the URL and the other is responsible for parsing it. In the next examples, a very basic and a more advanced one, we assume that we have three views that links can point to. The first is a categories overview (&lt;code&gt;view=categories&lt;/code&gt;), the second is a single category (&lt;code&gt;view=category&lt;/code&gt;) and the third is a single article (&lt;code&gt;view=article&lt;/code&gt;).<br />
<br />
The file &lt;tt&gt;router.php&lt;/tt&gt; should be in the site area of your component. It is not used on admin/backend pages. Don't forget to add it to your XML [[Manifest files|manifest file]] in the site folder.<br />
<br />
=== A Simple Example ===<br />
<br />
This simple example will illustrate the basics of implementing a router for your component.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]BuildRoute( &amp;$query )<br />
{<br />
$segments = array();<br />
if(isset($query['view']))<br />
{<br />
$segments[] = $query['view'];<br />
unset( $query['view'] );<br />
}<br />
if(isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset( $query['id'] );<br />
};<br />
return $segments;<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
&lt;code&gt;JRouter&lt;/code&gt; passes a $query array to the &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; function. This function will add the relevant parts of the array to the $segments array in the right order and will return the properly ordered array. The content of the &lt;code&gt;$query&lt;/code&gt; array needs to be unset, otherwise &lt;code&gt;JRouter&lt;/code&gt; will add it to the URL in the form of a query string (i.e. any variables that are not handled by the router will be passed in the query string).<br />
<br />
The prefix ''componentname'' is the name for your component, as found in the directory holding the component's files. For instance, a component &quot;Magic&quot; in directory &lt;tt&gt;/components/com_magic/...&lt;/tt&gt; would use a prefix &lt;code&gt;magic&lt;/code&gt; (all lower case).<br />
<br />
The next function in the &lt;tt&gt;router.php&lt;/tt&gt; parses the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute( $segments )<br />
{<br />
$vars = array();<br />
switch($segments[0])<br />
{<br />
case 'categories':<br />
$vars['view'] = 'categories';<br />
break;<br />
case 'category':<br />
$vars['view'] = 'category';<br />
$id = explode( ':', $segments[1] );<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'article':<br />
$vars['view'] = 'article';<br />
$id = explode( ':', $segments[1] );<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
What happens here? In the function &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; we arranged the items in the &lt;code&gt;$query&lt;/code&gt; array in a specific sequence. This means that in this example the view is first and the id is second in the array.<br />
<br />
By reading &lt;code&gt;$segments[0]&lt;/code&gt;, we access the name of the view. We set the right view and/or identifier depending on its value and we return the &lt;code&gt;$vars&lt;/code&gt; array to &lt;code&gt;JRouter&lt;/code&gt;. $vars should be an associative array similar to the array that was passed to the BuildRoute method.<br />
<br />
The above example of the &lt;tt&gt;router.php&lt;/tt&gt; is a very simple way to generate sef URL's but should show how this works quite clearly.<br />
<br />
The generated URL in this example contains the name of the view and doesn't reflect the content hierarchy:<br />
<br />
&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[view]/[slug]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
=== A More Advanced Example ===<br />
<br />
In the next example we will try to get rid of the need for the view and we will try to reflect the current hierarchy level in the URL.<br />
<br />
The goal is URL's that look like:<br />
<br />
* When viewing an article: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]/[article]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing a category: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]&lt;/nowiki&gt;&lt;/tt&gt;<br />
* When viewing the categories overview: &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/[menualias]&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
Let's assume we have done step 1 and 2 also for the category.<br />
<br />
The link to the article would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_( 'index.php?view=article&amp;catid='.$row-­&gt;catslug .'&amp;id='.$row-­&gt;slug );<br />
&lt;/source&gt;<br />
<br />
And the Link to the category would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_( 'index.php?view=category&amp;id='.$row-&gt;catslug );<br />
&lt;/source&gt;<br />
<br />
The corresponding &lt;tt&gt;router.php&lt;/tt&gt;:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function [''Componentname'']BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if(isset( $query['catid'] ))<br />
{<br />
$segments[] = $query['catid'];<br />
unset( $query['catid'] );<br />
};<br />
if( isset($query['id']) )<br />
{<br />
$segments[] = $query['id'];<br />
unset( $query['id'] );<br />
};<br />
unset( $query['view'] );<br />
return $segments;<br />
}<br />
&lt;/source&gt;<br />
<br />
The difference now is that we don’t add the name of the view to the &lt;code&gt;$segments&lt;/code&gt; array. We still unset the view key since otherwise, &lt;code&gt;JRouter&lt;/code&gt; would add it to the URL as part of the query string. Another new thing here is the additional parameter catid that we push into the &lt;code&gt;$segments&lt;/code&gt; array.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [''Componentname'']ParseRoute($segments)<br />
{<br />
$vars = array();<br />
$app =&amp; JFactory::getApplication();<br />
$menu =&amp; $app-&gt;getMenu();<br />
$item =&amp; $menu-&gt;getActive();<br />
// Count segments<br />
$count = count( $segments );<br />
//Handle View and Identifier<br />
switch( $item-&gt;query['view'] )<br />
{<br />
case 'categories':<br />
if($count == 1) {<br />
$vars['view'] = 'category';<br />
}<br />
if($count == 2) {<br />
$vars['view'] = 'article';<br />
}<br />
$id = explode( ':', $segments[$count-1] );<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'category':<br />
$id = explode( ':', $segments[$count-1] );<br />
$vars['id'] = (int) $id[0];<br />
$vars['view'] = 'article';<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
You can see that this ParseRoute function has a lot of different code parts in comparison to the previous. The reason for this is simple. We don’t have the name of the view in the &lt;code&gt;$segments&lt;/code&gt; array and we need to find another way to determine it.<br />
<br />
We need to find out which level of hierarchy we are in by receiving the root element. We do this by looking to the view name of the active menu item:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$item-­&gt;query['view']<br />
&lt;/source&gt;<br />
<br />
Also we need to know the number of items in the &lt;code&gt;$segments&lt;/code&gt; array:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$count = count( $segments );<br />
&lt;/source&gt;<br />
<br />
With this information we can correctly set the view for all possible three cases:<br />
<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has two items (&lt;code&gt;$catid&lt;/code&gt; and &lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to an article.<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has one item (&lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to a category.<br />
* The menu item is a link to a category. In this case, we know that any item in the &lt;code&gt;$segments&lt;/code&gt; array is the identifier for an article.<br />
<br />
The result of all this code is clean and human-readable component URLs.<br />
<br />
== Application Route Parsing ==<br />
<br />
The [[Application execution order]] outlines that the route (URL) is parsed immediately after initialisation is complete. Since fancy URL's are not treated (yet) in the Administrator, we will follow the route parsing process in detail when &lt;code&gt;JSite::route&lt;/code&gt; in the &lt;tt&gt;index.php&lt;/tt&gt; file.<br />
<br />
* Call to &lt;code&gt;JApplication::route&lt;/code&gt;<br />
** Clone the URI<br />
** Call to &lt;code&gt;JApplication::getRouter&lt;/code&gt;<br />
*** Call to &lt;code&gt;JRouter::getInstance&lt;/code&gt; passing the type (&quot;site&quot;)<br />
** Call to &lt;code&gt;JRouterSite::parse&lt;/code&gt; passing the URI<br />
*** Strip the suffix if applicable (added to $vars['format'])<br />
*** Re-set the route (URI)<br />
*** Call to &lt;code&gt;JRouter::parse&lt;/code&gt; passing the URI<br />
**** Call to &lt;code&gt;JRouterSite::_processParseRules&lt;/code&gt; passing the URI (this will call custom route rules)<br />
***** Call to &lt;code&gt;JRouter::_processParseRules&lt;/code&gt; passing the URI<br />
****** Call any custom routing rules (probably added via a system plugin using the &lt;code&gt;onAfterInitialise&lt;/code&gt; event trigger) passing the URI<br />
****** Returns an array of vars<br />
***** If SEF mode, replace &lt;code&gt;start&lt;/code&gt; variable with &lt;/code&gt;limitstart&lt;/code&gt;<br />
**** If raw mode, call to &lt;code&gt;JRouterSite::_parseRawRoute&lt;/code&gt; passing the URI<br />
**** If SEF mode, call to &lt;code&gt;JRouterSite::_parseSefRoute&lt;/code&gt; passing the URI<br />
***** If the route (the URI path) is empty, load it from the default menu item; set the active menu item as the default<br />
***** If first part is &lt;code&gt;/component/com_content&lt;/code&gt;, set the &lt;code&gt;option&lt;/code&gt; as the second segement. Null the &lt;code&gt;Itemid&lt;/code&gt;.<br />
***** Else, loop through menu alias values and take off segments that match as the menu tree is traversed. Set &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;Itemid&lt;/code&gt; based on the last menu item found.<br />
***** If the &lt;code&gt;Itemid&lt;/code&gt; is set in the URL, set the active menu item based on this value.<br />
***** Push the vars collected so far (eg, &lt;code&gt;option&lt;/code&gt;, &lt;code&gt;Itemid&lt;/code&gt;, etc) into the router object (&lt;code&gt;$this&lt;/code&gt;).<br />
***** If the route and &lt;code&gt;option&lt;/code&gt; is set, load the component router;<br />
***** Else, get the active menu item and get the route vars from it<br />
<br />
<br />
== Application Route Building ==<br />
<br />
TODO<br />
<br />
== Custom Router Rules ==<br />
<br />
TODO<br />
<br />
== Additional References ==<br />
<br />
There is a useful thread on this subject here: [[jtopic:148632]] (note, may be out of date)<br />
&lt;noinclude&gt;[[Category:Tutorials]][[Category:Component Development]][[Category:Search Engine Friendly URLs]]&lt;/noinclude&gt;</div>Mvangeest//docs.joomla.org/Supporting_SEF_URLs_in_your_componentSupporting SEF URLs in your component2012-11-24T17:33:38Z<p>Mvangeest: Added information</p>
<hr />
<div>{{incomplete}}<br />
{{:Search Engine Friendly URLs}}<br />
In Joomla!, each [[component]] is responsible for handling its own SEF URLs. Therefore, as the [[Developers|developer]] of a component, you will have to create your own '''router''' to allow your component to use SEF URLs.<br />
<br />
== The Concept ==<br />
<br />
Assuming you are following standard development practices, your component is probably using &quot;system URLs&quot; that look a lot like &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;, and your goal is to transform this into &lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;. As the developer, you have two tasks: signalling the system that certain pieces of text are URLs and need to be transformed, and explaining the system how to transform URLs.<br />
<br />
=== Applying &lt;code&gt;JRoute::_&lt;/code&gt; ===<br />
<br />
It is difficult and inefficient for Joomla! to figure out which parts of your component's output are URLs. To support SEF URLs, you will need to change URL-generating code so that it applies &lt;code&gt;JRoute::_&lt;/code&gt; before outputting the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
echo JRoute::_('index.php?view=article&amp;id=1&amp;catid=20');<br />
&lt;/source&gt;<br />
<br />
Notice that it is possible to leave out the parameters &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;Itemid&lt;/code&gt;. &lt;code&gt;option&lt;/code&gt; defaults to the name of the component currently being executed, and &lt;code&gt;Itemid&lt;/code&gt; defaults to the current menu item's ID.<br />
<br />
In general, you should only apply this to URLs that users and/or search engines are able to see. For example, there is no need to transform URLs used in redirects that immediately result in other redirects.<br />
<br />
If the user turns off SEF URLs in the site's settings, &lt;code&gt;JRoute::_&lt;/code&gt; will produce working non-SEF URLs without any changes to the code.<br />
<br />
=== Writing a router ===<br />
<br />
You'll also need to write a router, which is a single file with two functions that convert system URLs to and from SEF URLs. This file needs to be placed at &lt;tt&gt;/components/com_yourcomponent/router.php&lt;/tt&gt;.<br />
<br />
The first function, &lt;code&gt;[componentname]BuildRoute(&amp;$query)&lt;/code&gt;, must transform an array of URL parameters into an array of segments that will form the SEF URL. Schematically, the transformation works as follows:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/index.php?option=com_yourcomponent&amp;view=article&amp;id=1&amp;catid=20&amp;Itemid=50&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; &lt;code&gt;JRoute::_&lt;/code&gt;, called by your component or any other extension<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentBuildRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal routing (for display)<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
The second function, &lt;code&gt;[componentname]ParseRoute($segments)&lt;/code&gt;, must transform an array of segments back into an array of URL parameters. Schematically:<br />
<br />
:&lt;tt&gt;&lt;nowiki&gt;http://www.example.com/example-menu-item/20/1&lt;/nowiki&gt;&lt;/tt&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Joomla's internal routing<br />
<br />
:&lt;code&gt;$segments = array(20, 1);&lt;/code&gt;<br />
<br />
::&lt;span style=&quot;font-size: xx-large&quot;&gt;&amp;darr;&lt;/span&gt; Your router's &lt;code&gt;com_yourcomponentParseRoute&lt;/code&gt;<br />
<br />
:&lt;code&gt;$query = array('view' =&gt; 'article', 'id' =&gt; 1, 'catid' =&gt; 20)&lt;/code&gt;<br />
<br />
The two functions must cooperate in such a way that the original URL can be reconstructed. You can think of &lt;code&gt;BuildRoute&lt;/code&gt; as a form of [[wikipedia:Encoding|encoding]] and &lt;code&gt;ParseRoute&lt;/code&gt; as the corresponding decoding. When the original URL isn't properly reproduced, your component will stop working.<br />
<br />
== Preparing Your Data for Routing ==<br />
<br />
=== The Alias ===<br />
<br />
The first step is the generation of the so called alias. The alias is used in the URL instead of the title (the alias is the text you want to have in the URL). The alias has to be URI safe, which means accented UTF­8 characters are replaced by their ASCII­7 equivalents, white spaces by hyphens, etc.<br />
<br />
The alias can be defined by the user, but you should ensure that the above requirements for a URL safe alias are met. A good way to do so is to use the JTable::check() method during the save process. Have a look at this example code:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function check()<br />
{<br />
jimport( 'joomla.filter.output' );<br />
if(empty($this-&gt;alias)) {<br />
$this-&gt;alias = $this-&gt;title;<br />
}<br />
$this-&gt;alias = JFilterOutput::stringURLSafe($this-&gt;alias);<br />
<br />
/* All your other checks */<br />
return true;<br />
}<br />
&lt;/source&gt;<br />
<br />
If the alias field is empty the title will be used as alias. Then the alias will be made URLSafe using the JFilterOutput::stringURLSafe() method.<br />
<br />
=== The Slug ===<br />
<br />
Continuing with the same example, the &quot;slug&quot; - &quot;1­:welcome­-to­-joomla&quot; has two parts. The first part is the article identifier (id) and the second is the alias. They are separated by a colon. These two elements were combined during the database query in the model:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;$query = 'SELECT a.*, '.<br />
'CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(&quot;:&quot;, a.id, a.alias) ELSE a.id END as slug,'<br />
/*...*/;&lt;/source&gt;<br />
<br />
After this step the slug is used instead of the id.<br />
<br />
== Routing URLs ==<br />
<br />
The &lt;code&gt;JRoute::_&lt;/code&gt; method translates the internal Joomla! URL to a custom URL. &lt;code&gt;JRoute&lt;/code&gt; has three parameters and its prototype is:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_( $url, $xhtml = true, $ssl=null );&lt;/source&gt;<br />
<br />
Where:<br />
<br />
* &lt;code&gt;$url&lt;/code&gt; is a string containing the absolute or relative internal Joomla! URL.<br />
* &lt;code&gt;$xhtml&lt;/code&gt; is a boolean value that specifies whether or not the output should be in XHTML. This parameter is optional and if omitted defaults to true.<br />
* &lt;code&gt;$ssl&lt;/code&gt; is an integer value that specifies whether the URI should be secure. It should be set to 1 to force the URI to be secure using the global secure site URI, 0 to leave it in the same state as when it was passed, and -1 to force the URI to be unsecure using the global unsecure site URI.<br />
<br />
The most important parameter is &lt;code&gt;$url&lt;/code&gt;. A call to this method might look like:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;JRoute::_( 'index.php?view=article&amp;id='.$row-&gt;slug );&lt;/source&gt;<br />
<br />
&lt;code&gt;$row-­&gt;slug&lt;/code&gt; is the value that was generated in step 2 from a combination of id and title alias.<br />
<br />
Another advantage of using JRoute is that the router now handles $option (the component name) and the $Itemid (the menu item ID). The component itself doesn’t have to know its name ($option) or the active menu item ($Itemid) like it did in previous version of Joomla!.<br />
<br />
It is important that you think about the sequence of the URL parameter in this stage. This will be more clear when we have a deeper look at the router.php in the next section.<br />
<br />
The building process of JRouter is divided into two steps:<br />
<br />
* Create the application route. The application route is fully handled by JRouter and the component developer doesn’t have to do anything to make it work.<br />
* Create the component route. To create the component route, JRouter looks for the router.php in the component directory which is responsible for building the route for the component.<br />
<br />
== The Component Router ==<br />
<br />
We will have two functions in the router.php. One is responsible for building the URL and the other is responsible for parsing it. In the next examples, a very basic and a more advanced one, we assume that we have three views that links can point to. The first is a categories overview (view=categories), the second is a single category (view=category) and the third is a single article (view=article).<br />
<br />
The file router.php should be in the site area of your component. It is not used on admin/backend pages. Don't forget to add it to your installation XML in the site folder.<br />
<br />
=== A Simple Example ===<br />
<br />
This simple example will illustrate the basics of implementing a router for your component.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]BuildRoute( &amp;$query )<br />
{<br />
$segments = array();<br />
if(isset($query['view']))<br />
{<br />
$segments[] = $query['view'];<br />
unset( $query['view'] );<br />
}<br />
if(isset($query['id']))<br />
{<br />
$segments[] = $query['id'];<br />
unset( $query['id'] );<br />
};<br />
return $segments;<br />
}<br />
<br />
&lt;/source&gt;<br />
<br />
&lt;code&gt;JRouter&lt;/code&gt; passes a $query array to the &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; function. This function will add the relevant parts of the array to the $segments array in the right order and will return the properly ordered array. The content of the &lt;code&gt;$query&lt;/code&gt; array needs to be unset, otherwise &lt;code&gt;JRouter&lt;/code&gt; will add it to the URL in the form of a query string (i.e. any variables that are not handled by the router will be passed in the query string).<br />
<br />
The prefix ''componentname'' is the name for your component, as found in the directory holding the component's files. For instance, a component &quot;Magic&quot; in directory &lt;code&gt;/components/com_magic/...&lt;/code&gt; would use a prefix &lt;code&gt;magic&lt;/code&gt; (all lower case).<br />
<br />
The next function in the &lt;code&gt;router.php&lt;/code&gt; parses the URL:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [componentname]ParseRoute( $segments )<br />
{<br />
$vars = array();<br />
switch($segments[0])<br />
{<br />
case 'categories':<br />
$vars['view'] = 'categories';<br />
break;<br />
case 'category':<br />
$vars['view'] = 'category';<br />
$id = explode( ':', $segments[1] );<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'article':<br />
$vars['view'] = 'article';<br />
$id = explode( ':', $segments[1] );<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
What happens here? In the function &lt;code&gt;[''componentname'']BuildRoute&lt;/code&gt; we arranged the items in the &lt;code&gt;$query&lt;/code&gt; array in a specific sequence. This means that in this example the view is first and the id is second in the array.<br />
<br />
By reading &lt;code&gt;$segments[0]&lt;/code&gt;, we access the name of the view. We set the right view and/or identifier depending on its value and we return the &lt;code&gt;$vars&lt;/code&gt; array to &lt;code&gt;JRouter&lt;/code&gt;. $vars should be an associative array similar to the array that was passed to the BuildRoute method.<br />
<br />
The above example of the &lt;code&gt;router.php&lt;/code&gt; is a very simple way to generate sef URL's but should show how this works quite clearly.<br />
<br />
The generated URL in this example contains the name of the view and doesn't reflect the content hierarchy:<br />
<br />
&lt;code&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[view]/[slug]&lt;/nowiki&gt;&lt;/code&gt;<br />
<br />
=== A More Advanced Example ===<br />
<br />
In the next example we will try to get rid of the need for the view and we will try to reflect the current hierarchy level in the URL.<br />
<br />
The goal is URL's that look like:<br />
<br />
* When viewing an article: &lt;code&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]/[article]&lt;/nowiki&gt;&lt;/code&gt;<br />
* When viewing a category: &lt;code&gt;&lt;nowiki&gt;http://www.example.com/[menualias]/[category]&lt;/nowiki&gt;&lt;/code&gt;<br />
* When viewing the categories overview: &lt;code&gt;&lt;nowiki&gt;http://www.example.com/[menualias]&lt;/nowiki&gt;&lt;/code&gt;<br />
<br />
Let's assume we have done step 1 and 2 also for the category.<br />
<br />
The link to the article would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_( 'index.php?view=article&amp;catid='.$row-­&gt;catslug .'&amp;id='.$row-­&gt;slug );<br />
&lt;/source&gt;<br />
<br />
And the Link to the category would look like this:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
JRoute::_( 'index.php?view=category&amp;id='.$row-&gt;catslug );<br />
&lt;/source&gt;<br />
<br />
The corresponding &lt;code&gt;router.php&lt;/code&gt;:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
<br />
function [''Componentname'']BuildRoute(&amp;$query)<br />
{<br />
$segments = array();<br />
if(isset( $query['catid'] ))<br />
{<br />
$segments[] = $query['catid'];<br />
unset( $query['catid'] );<br />
};<br />
if( isset($query['id']) )<br />
{<br />
$segments[] = $query['id'];<br />
unset( $query['id'] );<br />
};<br />
unset( $query['view'] );<br />
return $segments;<br />
}<br />
&lt;/source&gt;<br />
<br />
The difference now is that we don’t add the name of the view to the &lt;code&gt;$segments&lt;/code&gt; array. We still unset the view key since otherwise, &lt;code&gt;JRouter&lt;/code&gt; would add it to the URL as part of the query string. Another new thing here is the additional parameter catid that we push into the &lt;code&gt;$segments&lt;/code&gt; array.<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
function [''Componentname'']ParseRoute($segments)<br />
{<br />
$vars = array();<br />
$app =&amp; JFactory::getApplication();<br />
$menu =&amp; $app-&gt;getMenu();<br />
$item =&amp; $menu-&gt;getActive();<br />
// Count segments<br />
$count = count( $segments );<br />
//Handle View and Identifier<br />
switch( $item-&gt;query['view'] )<br />
{<br />
case 'categories':<br />
if($count == 1) {<br />
$vars['view'] = 'category';<br />
}<br />
if($count == 2) {<br />
$vars['view'] = 'article';<br />
}<br />
$id = explode( ':', $segments[$count-1] );<br />
$vars['id'] = (int) $id[0];<br />
break;<br />
case 'category':<br />
$id = explode( ':', $segments[$count-1] );<br />
$vars['id'] = (int) $id[0];<br />
$vars['view'] = 'article';<br />
break;<br />
}<br />
return $vars;<br />
}<br />
&lt;/source&gt;<br />
<br />
You can see that this ParseRoute function has a lot of different code parts in comparison to the previous. The reason for this is simple. We don’t have the name of the view in the &lt;code&gt;$segments&lt;/code&gt; array and we need to find another way to determine it.<br />
<br />
We need to find out which level of hierarchy we are in by receiving the root element. We do this by looking to the view name of the active menu item:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$item-­&gt;query['view']<br />
&lt;/source&gt;<br />
<br />
Also we need to know the number of items in the &lt;code&gt;$segments&lt;/code&gt; array:<br />
<br />
&lt;source lang=&quot;php&quot;&gt;<br />
$count = count( $segments );<br />
&lt;/source&gt;<br />
<br />
With this information we can correctly set the view for all possible three cases:<br />
<br />
* The menu item is a link to the categories view and the &lt;code&gt;$segments&lt;/code&gt; array has two items (&lt;code&gt;$catid&lt;/code&gt; and &lt;code&gt;$id&lt;/code&gt;). In this case we know that we need to parse a link to an article.<br />
* The menu item is a link to the categories view and the $segments array has one item ($id). In this case we know that we need to parse a link to a category.<br />
* The menu item is a link to a category. In this case, we know that any item in the $segments array is the identifier for an article.<br />
<br />
The result of all this code is clean and human-readable component URLs.<br />
<br />
== Application Route Parsing ==<br />
<br />
The [[Application execution order]] outlines that the route (URL) is parsed immediately after initialisation is complete. Since fancy URL's are not treated (yet) in the Administrator, we will follow the route parsing process in detail when &lt;code&gt;JSite::route&lt;/code&gt; in the &lt;code&gt;index.php&lt;/code&gt; file.<br />
<br />
* Call to &lt;code&gt;JApplication::route&lt;/code&gt;<br />
** Clone the URI<br />
** Call to &lt;code&gt;JApplication::getRouter&lt;/code&gt;<br />
*** Call to &lt;code&gt;JRouter::getInstance&lt;/code&gt; passing the type (&quot;site&quot;)<br />
** Call to &lt;code&gt;JRouterSite::parse&lt;/code&gt; passing the URI<br />
*** Strip the suffix if applicable (added to $vars['format'])<br />
*** Re-set the route (URI)<br />
*** Call to &lt;code&gt;JRouter::parse&lt;/code&gt; passing the URI<br />
**** Call to &lt;code&gt;JRouterSite::_processParseRules&lt;/code&gt; passing the URI (this will call custom route rules)<br />
***** Call to &lt;code&gt;JRouter::_processParseRules&lt;/code&gt; passing the URI<br />
****** Call any custom routing rules (probably added via a system plugin using the &lt;code&gt;onAfterInitialise&lt;/code&gt; event trigger) passing the URI<br />
****** Returns an array of vars<br />
***** If SEF mode, replace &lt;code&gt;start&lt;/code&gt; variable with &lt;/code&gt;limitstart&lt;/code&gt;<br />
**** If raw mode, call to &lt;code&gt;JRouterSite::_parseRawRoute&lt;/code&gt; passing the URI<br />
**** If SEF mode, call to &lt;code&gt;JRouterSite::_parseSefRoute&lt;/code&gt; passing the URI<br />
***** If the route (the URI path) is empty, load it from the default menu item; set the active menu item as the default<br />
***** If first part is &lt;code&gt;/component/com_content&lt;/code&gt;, set the &lt;code&gt;option&lt;/code&gt; as the second segement. Null the &lt;code&gt;Itemid&lt;/code&gt;.<br />
***** Else, loop through menu alias values and take off segments that match as the menu tree is traversed. Set &lt;code&gt;option&lt;/code&gt; and &lt;code&gt;Itemid&lt;/code&gt; based on the last menu item found.<br />
***** If the &lt;code&gt;Itemid&lt;/code&gt; is set in the URL, set the active menu item based on this value.<br />
***** Push the vars collected so far (eg, &lt;code&gt;option&lt;/code&gt;, &lt;code&gt;Itemid&lt;/code&gt;, etc) into the router object (&lt;code&gt;$this&lt;/code&gt;).<br />
***** If the route and &lt;code&gt;option&lt;/code&gt; is set, load the component router;<br />
***** Else, get the active menu item and get the route vars from it<br />
<br />
<br />
== Application Route Building ==<br />
<br />
TODO<br />
<br />
== Custom Router Rules ==<br />
<br />
TODO<br />
<br />
== Additional References ==<br />
<br />
There is a useful thread on this subject here: [[jtopic:148632]] (note, may be out of date)<br />
&lt;noinclude&gt;[[Category:Tutorials]][[Category:Component Development]][[Category:Search Engine Friendly URLs]]&lt;/noinclude&gt;</div>Mvangeest