Creating a Simple Module: Difference between revisions
From Joomla! Documentation
m Changes line 1 to heading 2 and line "Scripts" to heading 3 |
Added deprecation notice and link to Joomla Manual |
||
| (28 intermediate revisions by 7 users not shown) | |||
| Line 1: | Line 1: | ||
<noinclude><languages /></noinclude> | <noinclude><languages /></noinclude> | ||
{{Warning|With the move of developer documentation to the Joomla Manual, this page is unlikely to be actively maintained. A similar tutorial is available at [https://manual.joomla.org/docs/building-extensions/modules/module-development-tutorial/ Joomla Manual Module Development Tutorial]}} | |||
{{Joomla version|version=4.x|comment=><translate><!--T:1--> Tutorial</translate>}} | {{Joomla version|version=4.x|comment=><translate><!--T:1--> Tutorial</translate>}} | ||
{{-}} | {{-}} | ||
| Line 5: | Line 8: | ||
{{-}} | {{-}} | ||
<translate><!--T:3--> This is a tutorial on how to Create a simple module for Joomla Version 4x.</translate> | <translate><!--T:3--> This is a tutorial on how to Create a simple module for Joomla Version 4x.</translate> | ||
<translate> | <translate> | ||
== Introduction == <!--T:4--> | == Introduction == <!--T:4--> | ||
| Line 13: | Line 16: | ||
* '''[[S:MyLanguage/Module|<translate><!--T:8--> Modules</translate>]]''' <br /><translate><!--T:9--> A module is an add-on to the site that extends the functionality. A module usually occupies a secondary portion of the web page and is not considered the primary focus of a page. It can be displayed on different positions and you can choose on which active menu items it should be displayed. Modules are lightweight and flexible extensions. They are used for small bits of the page that are generally less complex and are able to be seen across different components.</translate> | * '''[[S:MyLanguage/Module|<translate><!--T:8--> Modules</translate>]]''' <br /><translate><!--T:9--> A module is an add-on to the site that extends the functionality. A module usually occupies a secondary portion of the web page and is not considered the primary focus of a page. It can be displayed on different positions and you can choose on which active menu items it should be displayed. Modules are lightweight and flexible extensions. They are used for small bits of the page that are generally less complex and are able to be seen across different components.</translate> | ||
* '''[[S:MyLanguage/Plugin|<translate><!--T:10--> Plugins</translate>]]'''<br /><translate><!--T:11--> A Plugin manipulates output that is already generated by the system. It typically does not run as separate part of the site. It takes data from other sources (i.e. the content) and manipulates this data before displaying. A plugin typically work behind the scenes.</translate> | * '''[[S:MyLanguage/Plugin|<translate><!--T:10--> Plugins</translate>]]'''<br /><translate><!--T:11--> A Plugin manipulates output that is already generated by the system. It typically does not run as separate part of the site. It takes data from other sources (i.e. the content) and manipulates this data before displaying. A plugin typically work behind the scenes.</translate> | ||
* '''[[S:MyLanguage/Languages|<translate><!--T:12--> Languages</translate>]]'''<br />Probably the most basic extensions are languages. In essence the language package files consist of key/value pairs, which provide the translation of static text strings, assigned within the Joomla! source code. | * '''[[S:MyLanguage/Languages|<translate><!--T:12--> Languages</translate>]]'''<br /><translate><!--T:203--> Probably the most basic extensions are languages. In essence the language package files consist of key/value pairs, which provide the translation of static text strings, assigned within the Joomla! source code.</translate> | ||
* '''[[S:MyLanguage/Templates|<translate><!--T:13--> Templates</translate>]]'''<br /><translate><!--T:14--> A template is basically the design of your Joomla! powered website.</translate> | * '''[[S:MyLanguage/Templates|<translate><!--T:13--> Templates</translate>]]'''<br /><translate><!--T:14--> A template is basically the design of your Joomla! powered website.</translate> | ||
| Line 19: | Line 22: | ||
<translate><!--T:16--> | <translate><!--T:16--> | ||
* Installation (used for installing Joomla and have to delete after installation) | * Installation (used for installing Joomla and have to delete after installation) | ||
* Administrator ( | * Administrator (Backend - used for managing content) | ||
* Public or site ( | * Public or site (Frontend - used for displaying content) | ||
* CLI (used for accessing Joomla on the command line and for cron jobs) | * CLI (used for accessing Joomla on the command line and for cron jobs) | ||
* API (web services - used for creating APIs for machine accessible content)</translate> | * API (web services - used for creating APIs for machine accessible content)</translate> | ||
<translate> | <translate> | ||
<!--T:17--> | <!--T:17--> | ||
The installation application is used once. The administrator and public are used through the concept of ''components'' with ''modules''. Each module has a single entry point located in the ''modules'' and accordingly ''administrator/modules'' directory. This entry point is called <tt>''mod_modulename/mod_modulename.php''</tt> (the ''mod_'' prefix is a historical trace). The entry point for the login module is for '' | The installation application is used once. The administrator and public are used through the concept of ''components'' with ''modules''. Each module has a single entry point located in the ''modules'' and accordingly ''administrator/modules'' directory. This entry point is called <tt>''mod_modulename/mod_modulename.php''</tt> (the ''mod_'' prefix is a historical trace). The entry point for the login module is for example ''/mod_login/mod_login.php''.</translate> | ||
<translate> | <translate> | ||
=== Requirements === <!--T:18--> | === Requirements === <!--T:18--> | ||
</translate> | </translate> | ||
<translate><!--T:19--> You need Joomla! 4.x for this tutorial ( | <translate><!--T:19--> You need Joomla! 4.x installation available to use for this tutorial ([https://github.com/joomla/joomla-cms/releases Download latest release here])</translate> | ||
<translate><!--T:20--> You can download Joomla! 4 at [https://github.com/joomla/joomla-cms/ | <translate><!--T:20--> You can download Joomla! 4 at [https://github.com/joomla/joomla-cms/releases GitHub], on the [https://developer.joomla.org/nightly-builds.html Developer website] or you can create a free website at https://launch.joomla.org.</translate> | ||
<translate> | <translate> | ||
== Creating a | == Creating a Simple Module/Developing a Basic Module == <!--T:21--> | ||
</translate> | </translate> | ||
<translate><!--T:22--> You can see many examples of modules in the standard Joomla! install. For example:</translate> | <translate><!--T:22--> You can see many examples of modules in the standard Joomla! install. For example:</translate> | ||
<translate><!--T:23--> | <translate><!--T:23--> | ||
* Menus | * Menus | ||
* Latest News | * Latest News | ||
* Login form | * Login form | ||
| Line 53: | Line 56: | ||
<translate><!--T:28--> * <tt>mod_foo.xml</tt> - This file contains information about the module. It defines the files that need to be installed by the Joomla! installer and specifies configuration parameters for the module.</translate> | <translate><!--T:28--> * <tt>mod_foo.xml</tt> - This file contains information about the module. It defines the files that need to be installed by the Joomla! installer and specifies configuration parameters for the module.</translate> | ||
<translate><!--T:29--> * <tt>tmpl/default.php</tt> - This is the module template. This file will take the data collected by mod_foo.php and generate the HTML to be displayed on the page.</translate> | <translate><!--T:29--> * <tt>tmpl/default.php</tt> - This is the module template. This file will take the data collected by mod_foo.php and generate the HTML to be displayed on the page.</translate> | ||
<translate><!--T:30--> * <tt>language/en-GB/ | <translate><!--T:30--> * <tt>language/en-GB/mod_foo.ini</tt> and <tt>language/en-GB/mod_foo.sys.ini</tt>- This are the files that provide the text in United Kingdom English.</translate> | ||
<translate> | <translate> | ||
| Line 63: | Line 66: | ||
<translate><!--T:35--> The helper class is imported to our current scope at the begin of the file.</translate> | <translate><!--T:35--> The helper class is imported to our current scope at the begin of the file.</translate> | ||
< | <syntaxhighlight lang="php">use Joomla\CMS\Helper\ModuleHelper;</syntaxhighlight> | ||
<translate><!--T:36--> Last we include the template to display the output via</translate> | <translate><!--T:36--> Last we include the template to display the output via</translate> | ||
< | <syntaxhighlight lang="php">require ModuleHelper::getLayoutPath('mod_foo', $params->get('layout', 'default'));</syntaxhighlight> | ||
<translate> | <translate> | ||
==== Completed mod_foo.php | ==== Completed mod_foo.php File ==== <!--T:37--> | ||
</translate> | </translate> | ||
<translate><!--T:38--> The complete <tt>mod_foo.php</tt> file is as follows:</translate> | <translate><!--T:38--> The complete <tt>mod_foo.php</tt> file is as follows:</translate> | ||
< | <syntaxhighlight lang="php"> | ||
<?php | <?php | ||
/** | /** | ||
| Line 85: | Line 88: | ||
* @link [AUTHOR_URL] | * @link [AUTHOR_URL] | ||
*/ | */ | ||
// No direct access to this file | |||
defined('_JEXEC') or die; | |||
use Joomla\CMS\Helper\ModuleHelper; | use Joomla\CMS\Helper\ModuleHelper; | ||
require ModuleHelper::getLayoutPath('mod_foo', $params->get('layout', 'default')); | require ModuleHelper::getLayoutPath('mod_foo', $params->get('layout', 'default')); | ||
</syntaxhighlight> | |||
<translate><!--T:39--> ''Side note''ː In Joomla 3x you usually used a line like <tt>$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx'));</tt>. You don't need this anymore. See this PRː https://github.com/joomla/joomla-cms/pull/17447.</translate> | |||
<translate><!--T:39--> ''Side note''ː In Joomla 3x you usually used a line like <tt>$moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx'));</tt>. You don't need this anymore. See this PRː https://github.com/joomla/joomla-cms/pull/17447.</translate> | |||
<translate><!--T:40--> The one line that we haven’t explained so far is the first line <tt>defined('_JEXEC') or die;</tt>. This line checks to make sure that this file is being included from the Joomla application. This is necessary to prevent variable injection and other potential security concerns.</translate> | <translate><!--T:40--> The one line that we haven’t explained so far is the first line <tt>defined('_JEXEC') or die;</tt>. This line checks to make sure that this file is being included from the Joomla application. This is necessary to prevent variable injection and other potential security concerns.</translate> | ||
| Line 107: | Line 110: | ||
</translate> | </translate> | ||
<translate><!--T:44--> The code for the tmpl/default.php file is as follows:</translate> | <translate><!--T:44--> The code for the tmpl/default.php file is as follows:</translate> | ||
< | <syntaxhighlight lang="php"> | ||
<?php | <?php | ||
/** | /** | ||
| Line 119: | Line 122: | ||
*/ | */ | ||
// No direct access to this file | |||
defined('_JEXEC') or die; | defined('_JEXEC') or die; | ||
echo '[PROJECT_NAME]'; | echo '[PROJECT_NAME]'; | ||
</syntaxhighlight> | |||
</ | |||
<translate><!--T:45--> An important point to note is that the template file has the same scope as the <tt>mod_foo.php</tt> file. It means that a variable can be defined in the <tt>mod_foo.php</tt> file and then used in the template file without any extra declarations or function calls.</translate> | <translate><!--T:45--> An important point to note is that the template file has the same scope as the <tt>mod_foo.php</tt> file. It means that a variable can be defined in the <tt>mod_foo.php</tt> file and then used in the template file without any extra declarations or function calls.</translate> | ||
| Line 136: | Line 139: | ||
</translate> | </translate> | ||
<translate><!--T:49--> The code for the <tt>mod_foo.xml</tt> file is as follows:</translate> | <translate><!--T:49--> The code for the <tt>mod_foo.xml</tt> file is as follows:</translate> | ||
<syntaxhighlight lang="xml"> | |||
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||
<extension type="module" version=" | <extension type="module" version="4.0" client="site" method="upgrade"> | ||
<name>MOD_FOO</name> | <name>MOD_FOO</name> | ||
<creationDate>[DATE]</creationDate> | <creationDate>[DATE]</creationDate> | ||
| Line 150: | Line 152: | ||
<version>1.0</version> | <version>1.0</version> | ||
<description>MOD_FOO_XML_DESCRIPTION</description> | <description>MOD_FOO_XML_DESCRIPTION</description> | ||
<files> | <files> | ||
<filename module="mod_foo">mod_foo.php</filename> | <filename module="mod_foo">mod_foo.php</filename> | ||
| Line 157: | Line 158: | ||
<filename>mod_foo.xml</filename> | <filename>mod_foo.xml</filename> | ||
</files> | </files> | ||
</extension> | </extension> | ||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
=== Creating the | === Creating the Language Files === <!--T:50--> | ||
</translate> | </translate> | ||
<translate><!--T:51--> The files <tt>language/en-GB/ | <translate><!--T:51--> The files <tt>language/en-GB/mod_foo.ini</tt> and <tt>language/en-GB/mod_foo.sys.ini</tt> are used to translate text in the Frontend and in the Backend. Note that the language file structure has been updated in Joomla 4, and language prefixes on the individual files in a language folder are no longer required.</translate> | ||
<translate><!--T:52--> The code for <tt>language/en-GB/ | <translate><!--T:52--> The code for <tt>language/en-GB/mod_foo.sys.ini</tt> is as follows:</translate> | ||
<syntaxhighlight lang="xml"> | |||
MOD_FOO="[PROJECT_NAME]" | MOD_FOO="[PROJECT_NAME]" | ||
MOD_FOO_XML_DESCRIPTION="Foo Module" | MOD_FOO_XML_DESCRIPTION="Foo Module" | ||
</syntaxhighlight> | |||
</ | <translate><!--T:204--> The code for <tt>language/en-GB/mod_foo.ini</tt> is as follows:</translate> | ||
< | |||
<syntaxhighlight lang="xml"> | |||
MOD_FOO="[PROJECT_NAME]" | MOD_FOO="[PROJECT_NAME]" | ||
MOD_FOO_XML_DESCRIPTION="Foo Module" | MOD_FOO_XML_DESCRIPTION="Foo Module" | ||
</syntaxhighlight> | |||
<translate><!--T:53--> The <tt>.sys.ini</tt> file is used to translate the description of the extension upon installation, where as the <tt>.ini</tt> file is used to translate the remaining strings and the description when viewing your extension.</translate> | |||
<translate><!--T:53--> The <tt>.sys.ini</tt> file is used to translate the description of the extension upon installation, where as the <tt>.ini</tt> file is used to translate the remaining strings and the description when viewing your extension.</translate> | |||
<translate><!--T:54--> More information about language files can be found [[S:MyLanguage/Specification_of_language_files|here]].</translate> | <translate><!--T:54--> More information about language files can be found [[S:MyLanguage/Specification_of_language_files|here]].</translate> | ||
<translate> | <translate> | ||
== Test | == Test Your Module == <!--T:55--> | ||
</translate> | </translate> | ||
<translate><!--T:56--> Now you can zip all files and install them via the Joomla Extension Manager.<br /></translate> | <translate><!--T:56--> Now you can zip all files and install them via the Joomla Extension Manager.<br /></translate> | ||
<translate><!--T:57--> After that you can choose your module in the module manager, when you create a new site module.</translate> | <translate><!--T:57--> After that you can choose your module in the module manager, when you create a new site module.</translate> | ||
{{-}} | {{-}} | ||
[[File:moduletutorial1-<translate><!--T:58--> en</translate>.png|700px|center]] | [[File:moduletutorial1-<translate><!--T:58--> en</translate>.png|700px|center]] | ||
| Line 197: | Line 194: | ||
[[File:moduletutorial2-<translate><!--T:59--> en</translate>.png|700px|center]] | [[File:moduletutorial2-<translate><!--T:59--> en</translate>.png|700px|center]] | ||
<translate><!--T:60--> In the | <translate><!--T:60--> In the Frontend, you will see your module like displayed in the next image.</translate> | ||
{{-}} | {{-}} | ||
[[File:moduletutorial3-<translate><!--T:61--> en</translate>.png|700px|center]] | [[File:moduletutorial3-<translate><!--T:61--> en</translate>.png|700px|center]] | ||
| Line 207: | Line 204: | ||
<translate><!--T:64--> You can find boilerplates hereː</translate> | <translate><!--T:64--> You can find boilerplates hereː</translate> | ||
* https://github.com/joomla-extensions/boilerplate/tree/master/ | * https://github.com/joomla-extensions/boilerplate/tree/master/module | ||
<translate><!--T:65--> The sample files for this Tutorial can be found hereː</translate> | <translate><!--T:65--> The sample files for this Tutorial can be found hereː</translate> | ||
* https://github.com/astridx/boilerplate/tree/tutorial/tutorial/modules | * https://github.com/astridx/boilerplate/tree/tutorial/tutorial/modules | ||
<translate> | <translate> | ||
== Add a Helper Class Using Namespaces == <!--T:66--> | |||
== Add a | |||
</translate> | </translate> | ||
| Line 219: | Line 215: | ||
=== Requirements === <!--T:67--> | === Requirements === <!--T:67--> | ||
</translate> | </translate> | ||
<translate><!--T:68--> You need Joomla! 4.x for this tutorial | <translate><!--T:68--> You need Joomla! 4.x for this tutorial.</translate> | ||
<translate> | <translate> | ||
== Namespaces == <!--T:69--> | == Namespaces == <!--T:69--> | ||
</translate> | </translate> | ||
<translate><!--T:70--> With PHP 5.3, the namespaces came into their own. In other programming languages for a long time in use, these small structures now also help us with the clarity of our code.</translate> | <translate><!--T:70--> With PHP 5.3, the namespaces came into their own. In other programming languages for a long time in use, these small structures now also help us with the clarity of our code.</translate> | ||
<translate><!--T:71--> Namespaces are separate areas in which certain logical things (in our case, classes, interfaces, functions, and constants) can live. These areas provide | <translate><!--T:71--> Namespaces are separate areas in which certain logical things (in our case, classes, interfaces, functions, and constants) can live. These areas provide encapsulation of the code and prevent name conflicts.</translate> | ||
<translate><!--T:72--> Let's take a look how to use them in Joomla 4. We use the helper file for this.</translate> | <translate><!--T:72--> Let's take a look how to use them in Joomla 4. We use the helper file for this.</translate> | ||
| Line 236: | Line 232: | ||
<translate><!--T:75--> | <translate><!--T:75--> | ||
* <code>Helper/FooHelper.php</code> - This is the file we use here as an example. We have to create it. | * <code>Helper/FooHelper.php</code> - This is the file we use here as an example. We have to create it. | ||
* <code>mod_foo.php</code> - In this file we will mainly load the namespace. | * <code>mod_foo.php</code> - In this file, we will mainly load the namespace. | ||
* <code>tmpl/default.php</code> - In this file demonstrate how the data of a helper can be displayed. | * <code>tmpl/default.php</code> - In this file, we will demonstrate how the data of a helper can be displayed. | ||
* <code>mod_foo.xml</code> - We create a new directory with a new file. This must be installed during the installation. For this we have to specify them in this file.</translate> | * <code>mod_foo.xml</code> - We create a new directory with a new file. This must be installed during the installation. For this we have to specify them in this file.</translate> | ||
| Line 244: | Line 240: | ||
</translate> | </translate> | ||
<translate><!--T:77--> Our new helper class should belong to a namespace. We achieve this with the following code. It is important, that this line is at the beginning of the file.</translate> | <translate><!--T:77--> Our new helper class should belong to a namespace. We achieve this with the following code. It is important, that this line is at the beginning of the file.</translate> | ||
<syntaxhighlight lang="php">namespace Joomla\Module\Foo\Site\Helper;</syntaxhighlight> | |||
<translate><!--T:78--> Then we create a simple class with a simple method. Of course you can do a lot more here. Take a look at the Joomla core methods. Here are many examples. They show you first-hand what options you have.</translate> | <translate><!--T:78--> Then we create a simple class with a simple method. Of course you can do a lot more here. Take a look at the Joomla core methods. Here are many examples. They show you first-hand what options you have.</translate> | ||
| Line 252: | Line 247: | ||
==== Completed Helper/FooHelper.php ==== <!--T:79--> | ==== Completed Helper/FooHelper.php ==== <!--T:79--> | ||
</translate> | </translate> | ||
<translate><!--T:80--> The complete <tt> | <translate><!--T:80--> The complete <tt>FooHelper.php</tt> file is as follows:</translate> | ||
<syntaxhighlight lang="php"> | |||
<?php | <?php | ||
/** | /** | ||
* @package Joomla.Site | * @package Joomla.Site | ||
* @subpackage | * @subpackage mod_foo | ||
* | * | ||
* @copyright Copyright (C) 2005 - | * @copyright Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved. | ||
* @license GNU General Public License version 2 or later; see LICENSE.txt | * @license GNU General Public License version 2 or later; see LICENSE.txt | ||
*/ | */ | ||
| Line 267: | Line 261: | ||
namespace Joomla\Module\Foo\Site\Helper; | namespace Joomla\Module\Foo\Site\Helper; | ||
// No direct access to this file | |||
defined('_JEXEC') or die; | defined('_JEXEC') or die; | ||
| Line 289: | Line 284: | ||
} | } | ||
} | } | ||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
=== Editing mod_foo.php === <!--T:81--> | === Editing mod_foo.php === <!--T:81--> | ||
</translate> | </translate> | ||
<translate><!--T:82--> Our new helper class is imported to our current scope at the | <translate><!--T:82--> Our new helper class is imported to our current scope at the beginning of the file.</translate> | ||
< | <syntaxhighlight lang="php">use Joomla\Module\Foo\Site\Helper\FooHelper;</syntaxhighlight> | ||
<translate><!--T:83--> Last use the helper file for testing if it is loaded correctlyː</translate> | <translate><!--T:83--> Last use the helper file for testing if it is loaded correctlyː</translate> | ||
< | <syntaxhighlight lang="php">$test = FooHelper::getText($params, $app);</syntaxhighlight> | ||
<translate> | <translate> | ||
| Line 307: | Line 301: | ||
</translate> | </translate> | ||
<translate><!--T:85--> The complete <tt>mod_foo.php</tt> file is as follows:</translate> | <translate><!--T:85--> The complete <tt>mod_foo.php</tt> file is as follows:</translate> | ||
<syntaxhighlight lang="php"> | |||
<?php | <?php | ||
/** | /** | ||
| Line 320: | Line 313: | ||
*/ | */ | ||
// No direct access to this file | |||
defined('_JEXEC') or die; | defined('_JEXEC') or die; | ||
| Line 328: | Line 322: | ||
require ModuleHelper::getLayoutPath('mod_foo', $params->get('layout', 'default')); | require ModuleHelper::getLayoutPath('mod_foo', $params->get('layout', 'default')); | ||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
=== Editing tmpl/default.php === <!--T:86--> | === Editing tmpl/default.php === <!--T:86--> | ||
</translate> | </translate> | ||
<translate><!--T:87--> In this file you make only a small change to demonstrate in the | <translate><!--T:87--> In this file you make only a small change to demonstrate in the Frontend that your helper file is working properly. You only add the value of the variable at the end of the current output.</translate> | ||
< | <syntaxhighlight lang="php">echo '[PROJECT_NAME]' . $test;</syntaxhighlight> | ||
<translate> | <translate> | ||
| Line 342: | Line 335: | ||
</translate> | </translate> | ||
<translate><!--T:89--> The complete <tt>tmpl/default.php</tt> file is as follows:</translate> | <translate><!--T:89--> The complete <tt>tmpl/default.php</tt> file is as follows:</translate> | ||
<syntaxhighlight lang="php"> | |||
<?php | <?php | ||
/** | /** | ||
| Line 355: | Line 347: | ||
*/ | */ | ||
// No direct access to this file | |||
defined('_JEXEC') or die; | defined('_JEXEC') or die; | ||
echo '[PROJECT_NAME]' . $test; | |||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
| Line 367: | Line 357: | ||
</translate> | </translate> | ||
<translate><!--T:91--> First you have to add a line, so that the namespace is set automatically in Joomla. After this change, you have to re-install your module. A simple change in an already installed module is not enough. If you are doing local development you can also delete the files libraries/autoload_psr4.php and it will automatically be re-created. After inserting and installing, the namespace is known by the loader <tt>JPATH_LIBRARIES . '/autoload_psr4.php'</tt>.</translate> | <translate><!--T:91--> First you have to add a line, so that the namespace is set automatically in Joomla. After this change, you have to re-install your module. A simple change in an already installed module is not enough. If you are doing local development you can also delete the files libraries/autoload_psr4.php and it will automatically be re-created. After inserting and installing, the namespace is known by the loader <tt>JPATH_LIBRARIES . '/autoload_psr4.php'</tt>.</translate> | ||
< | <syntaxhighlight lang="xml"><namespace>Joomla\Module\Foo</namespace></syntaxhighlight> | ||
<translate><!--T:92--> Joomla! should copy your helper file when installing the module. So Joomla! needs to know your helper file. For this, you need to add the following line to your XML file.</translate> | <translate><!--T:92--> Joomla! should copy your helper file when installing the module. So Joomla! needs to know your helper file. For this, you need to add the following line to your XML file.</translate> | ||
< | <syntaxhighlight lang="xml"><folder>Helper</folder></syntaxhighlight> | ||
<translate> | <translate> | ||
| Line 378: | Line 368: | ||
</translate> | </translate> | ||
<translate><!--T:94--> The complete <tt>mod_foo.xml</tt> file is as follows:</translate> | <translate><!--T:94--> The complete <tt>mod_foo.xml</tt> file is as follows:</translate> | ||
< | <syntaxhighlight lang="xml"> | ||
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||
<extension type="module" version=" | <extension type="module" version="4.0" client="site" method="upgrade"> | ||
<name>MOD_FOO</name> | <name>MOD_FOO</name> | ||
<creationDate>[DATE]</creationDate> | <creationDate>[DATE]</creationDate> | ||
| Line 400: | Line 390: | ||
<filename>mod_foo.xml</filename> | <filename>mod_foo.xml</filename> | ||
</files> | </files> | ||
</extension> | </extension> | ||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
== Test | == Test Your Module == <!--T:95--> | ||
</translate> | </translate> | ||
<translate><!--T:96--> Now you can zip all files and install them via the Joomla Extension Manager.</translate> | <translate><!--T:96--> Now you can zip all files and install them via the Joomla Extension Manager.</translate> | ||
<translate><!--T:97--> After that you can choose your module in the module manager, when you create a new site module.</translate> | <translate><!--T:97--> After that you can choose your module in the module manager, when you create a new site module.</translate> | ||
<translate><!--T:98--> In the | <translate><!--T:98--> In the Frontend you will see your module like displayed in the next image. The text from your helper file is displayed.</translate> | ||
{{-}} | {{-}} | ||
[[File:moduletutorial23-<translate><!--T:99--> en</translate>.png|700px|center]] | [[File:moduletutorial23-<translate><!--T:99--> en</translate>.png|700px|center]] | ||
| Line 421: | Line 409: | ||
<translate><!--T:102--> You can find boilerplates hereː</translate> | <translate><!--T:102--> You can find boilerplates hereː</translate> | ||
* https://github.com/joomla-extensions/boilerplate/tree/master/ | * https://github.com/joomla-extensions/boilerplate/tree/master/module | ||
<translate><!--T:103--> The sample files for this Tutorial can be found hereː</translate> | <translate><!--T:103--> The sample files for this Tutorial can be found hereː</translate> | ||
* https://github.com/astridx/boilerplate/tree/tutorial/tutorial/modules | * https://github.com/astridx/boilerplate/tree/tutorial/tutorial/modules | ||
<translate> | <translate> | ||
== Customizationː Add Parameters Via Form Fields == <!--T:104--> | |||
== Customizationː Add | |||
</translate> | </translate> | ||
| Line 433: | Line 420: | ||
=== Requirements === <!--T:105--> | === Requirements === <!--T:105--> | ||
</translate> | </translate> | ||
<translate><!--T:106--> You need Joomla! 4.x for this tutorial | <translate><!--T:106--> You need Joomla! 4.x for this tutorial.</translate> | ||
<translate> | <translate> | ||
== Customization with | == Customization with Form Fields and Parameters == <!--T:107--> | ||
</translate> | </translate> | ||
<translate><!--T:108--> Form fields give a great deal of customization in Joomla and for modules are the sole way of allowing the user to tweak the module to the needs of their site.</translate> | <translate><!--T:108--> Form fields give a great deal of customization in Joomla and for modules are the sole way of allowing the user to tweak the module to the needs of their site.</translate> | ||
<translate><!--T:109--> In this case we are going to extend our previous example using a | <translate><!--T:109--> In this case we are going to extend our previous example using a URL field for inserting a domain that we can use as link in the front end. To allow this to happen we will use the [[S:MyLanguage/URL_form_field_type|URL Form Field]] type.</translate> | ||
<translate><!--T:110--> After that, we insert parameters that allow to use standard functionality of Joomla.</translate> | <translate><!--T:110--> After that, we insert parameters that allow to use standard functionality of Joomla.</translate> | ||
| Line 458: | Line 445: | ||
=== Editing mod_foo.xml === <!--T:115--> | === Editing mod_foo.xml === <!--T:115--> | ||
</translate> | </translate> | ||
<translate><!--T:116--> First we set a custom parameter.</translate | <translate><!--T:116--> First we set a custom parameter.</translate> | ||
<syntaxhighlight lang="xml"> | |||
<field | <field | ||
name="domain" | name="domain" | ||
| Line 468: | Line 454: | ||
filter="url" | filter="url" | ||
/> | /> | ||
</syntaxhighlight> | |||
</ | |||
<translate><!--T:117--> Then we insert Joomla default fields, so that we can use cache, moduleclass-suffix and layouts.</translate> | <translate><!--T:117--> Then we insert Joomla default fields, so that we can use cache, moduleclass-suffix and layouts.</translate> | ||
< | <syntaxhighlight lang="xml"> | ||
<field | <field | ||
name="layout" | name="layout" | ||
| Line 512: | Line 497: | ||
<option value="itemid"></option> | <option value="itemid"></option> | ||
</field> | </field> | ||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
| Line 519: | Line 503: | ||
</translate> | </translate> | ||
<translate><!--T:119--> The complete <tt>mod_foo.xml</tt> file is as follows:</translate> | <translate><!--T:119--> The complete <tt>mod_foo.xml</tt> file is as follows:</translate> | ||
<syntaxhighlight lang="xml"> | |||
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||
<extension type="module" version=" | <extension type="module" version="4.0" client="site" method="upgrade"> | ||
<name>MOD_FOO</name> | <name>MOD_FOO</name> | ||
<creationDate>[DATE]</creationDate> | <creationDate>[DATE]</creationDate> | ||
| Line 558: | Line 541: | ||
class="custom-select" | class="custom-select" | ||
/> | /> | ||
<field | <field | ||
name="moduleclass_sfx" | name="moduleclass_sfx" | ||
| Line 565: | Line 547: | ||
rows="3" | rows="3" | ||
/> | /> | ||
<field | <field | ||
name="cache" | name="cache" | ||
| Line 575: | Line 556: | ||
<option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option> | <option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option> | ||
</field> | </field> | ||
<field | <field | ||
name="cache_time" | name="cache_time" | ||
| Line 582: | Line 562: | ||
default="0" | default="0" | ||
/> | /> | ||
<field | <field | ||
name="cachemode" | name="cachemode" | ||
| Line 594: | Line 573: | ||
</config> | </config> | ||
</extension> | </extension> | ||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
=== Editing tmpl/default.php === <!--T:120--> | === Editing tmpl/default.php === <!--T:120--> | ||
</translate> | </translate> | ||
<translate><!--T:121--> We can use the value of the parameter for creating | <translate><!--T:121--> We can use the value of the parameter for creating a hyperlink in the Frontend. We can access the value via the variable $params.</translate> | ||
< | <syntaxhighlight lang="php">$domain = $params->get('domain', 'https://www.joomla.org');</syntaxhighlight> | ||
<translate><!--T:122--> Later we set use this value for creating the hyperlink.</translate> | <translate><!--T:122--> Later we set use this value for creating the hyperlink.</translate> | ||
<syntaxhighlight lang="php"> | |||
<a href="<?php echo $domain; ?>"> | <a href="<?php echo $domain; ?>"> | ||
<?php echo '[PROJECT_NAME]' . $test; ?> | <?php echo '[PROJECT_NAME]' . $test; ?> | ||
</a> | </a> | ||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
| Line 618: | Line 594: | ||
</translate> | </translate> | ||
<translate><!--T:124--> The complete <tt>tmpl/default.php</tt> file is as follows:</translate> | <translate><!--T:124--> The complete <tt>tmpl/default.php</tt> file is as follows:</translate> | ||
< | <syntaxhighlight lang="php"> | ||
<?php | <?php | ||
| Line 631: | Line 607: | ||
*/ | */ | ||
// No direct access to this file | |||
defined('_JEXEC') or die; | defined('_JEXEC') or die; | ||
| Line 639: | Line 616: | ||
<?php echo '[PROJECT_NAME]' . $test; ?> | <?php echo '[PROJECT_NAME]' . $test; ?> | ||
</a> | </a> | ||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
| Line 646: | Line 622: | ||
</translate> | </translate> | ||
<translate><!--T:126--> Here we can specify the text for the English version of the field label.</translate> | <translate><!--T:126--> Here we can specify the text for the English version of the field label.</translate> | ||
< | <syntaxhighlight lang="php">MOD_FOO_FIELD_URL_LABEL="Url"</syntaxhighlight> | ||
<translate> | <translate> | ||
| Line 653: | Line 629: | ||
</translate> | </translate> | ||
<translate><!--T:128--> The complete <tt>language/en-GB/en-GB.mod_foo.ini</tt> file is as follows:</translate> | <translate><!--T:128--> The complete <tt>language/en-GB/en-GB.mod_foo.ini</tt> file is as follows:</translate> | ||
<syntaxhighlight lang="php"> | |||
MOD_FOO="[PROJECT_NAME]" | MOD_FOO="[PROJECT_NAME]" | ||
MOD_FOO_XML_DESCRIPTION="Foo Module" | MOD_FOO_XML_DESCRIPTION="Foo Module" | ||
MOD_FOO_FIELD_URL_LABEL="Url" | MOD_FOO_FIELD_URL_LABEL="Url" | ||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
== Test | == Test Your Module == <!--T:129--> | ||
</translate> | </translate> | ||
<translate><!--T:130--> Now you can zip all files and install them via the Joomla Extension Manager.</translate> | <translate><!--T:130--> Now you can zip all files and install them via the Joomla Extension Manager.</translate> | ||
<translate><!--T:131--> After that you can choose your module in the module manager, when you create a new site module.</translate> | <translate><!--T:131--> After that you can choose your module in the module manager, when you create a new site module.</translate> | ||
<translate><!--T:132--> In the | <translate><!--T:132--> In the Backend, you will see your module like displayed in the next image.</translate> | ||
<translate><!--T:133--> In the basic tab, you will see the custom field where you can insert a domain. The text for the label is fetched from the language file.</translate> | <translate><!--T:133--> In the basic tab, you will see the custom field where you can insert a domain. The text for the label is fetched from the language file.</translate> | ||
{{-}} | {{-}} | ||
[[File:moduletutorial31-<translate><!--T:134--> en</translate>.png|700px|center]] | [[File:moduletutorial31-<translate><!--T:134--> en</translate>.png|700px|center]] | ||
| Line 678: | Line 652: | ||
[[File:moduletutorial32-<translate><!--T:136--> en</translate>.png|700px|center]] | [[File:moduletutorial32-<translate><!--T:136--> en</translate>.png|700px|center]] | ||
<translate><!--T:137--> In the | <translate><!--T:137--> In the Frontend, you will see your module like displayed in the next image. The text form your helper file is displayed and you should see a hyperlink.</translate> | ||
{{-}} | {{-}} | ||
[[File:moduletutorial33-<translate><!--T:138--> en</translate>.png|700px|center]] | [[File:moduletutorial33-<translate><!--T:138--> en</translate>.png|700px|center]] | ||
| Line 685: | Line 659: | ||
== Conclusion == <!--T:139--> | == Conclusion == <!--T:139--> | ||
</translate> | </translate> | ||
<translate><!--T:140--> Form fields give the user an easy way to customize the module to their sites settings. This allows the modules scope to be increased.</translate> | <translate><!--T:140--> Form fields give the user an easy way to customize the module to their sites settings. This allows the modules scope to be increased.</translate> | ||
<translate><!--T:141--> You can find boilerplates hereː</translate> | <translate><!--T:141--> You can find boilerplates hereː</translate> | ||
* https://github.com/joomla-extensions/boilerplate/tree/master/ | * https://github.com/joomla-extensions/boilerplate/tree/master/module | ||
<translate><!--T:142--> The sample files for this Tutorial can be found hereː</translate> | <translate><!--T:142--> The sample files for this Tutorial can be found hereː</translate> | ||
* https://github.com/astridx/boilerplate/tree/tutorial/tutorial/modules | * https://github.com/astridx/boilerplate/tree/tutorial/tutorial/modules | ||
| Line 695: | Line 669: | ||
<translate> | <translate> | ||
== Use Install, Update and Uninstall Script == <!--T:144--> | |||
== Use Install, Update and Uninstall | |||
</translate> | </translate> | ||
| Line 702: | Line 675: | ||
=== Requirements === <!--T:145--> | === Requirements === <!--T:145--> | ||
</translate> | </translate> | ||
<translate><!--T:146--> You need Joomla! 4.x for this tutorial | <translate><!--T:146--> You need Joomla! 4.x for this tutorial.</translate> | ||
<translate> | <translate> | ||
| Line 729: | Line 702: | ||
=== Creating script.php === <!--T:154--> | === Creating script.php === <!--T:154--> | ||
</translate> | </translate> | ||
<translate><!--T:155--> Writing an extension script consists in declaring a class whose name is <tt> | <translate><!--T:155--> Writing an extension script consists in declaring a class whose name is <tt>mod_ModuleNameInstallerScript</tt> with these 5 methods. See the comments in the file for more information. In this comments I explain when a method is called.</translate> | ||
<translate><!--T:156--> In this example, I only use text to show when which method will be executed. In addition, I show you how to check the minimum requirements. Of course you can do much more. For example, you can delete files that are no longer needed in a new version of your module. This can be seen in the file. Another idea for this file is to create sample content, to show a success message with the current installed version number or you can redirect after a successful installation to the page with the module settings.</translate> | <translate><!--T:156--> In this example, I only use text to show when which method will be executed. In addition, I show you how to check the minimum requirements. Of course you can do much more. For example, you can delete files that are no longer needed in a new version of your module. This can be seen in the file. Another idea for this file is to create sample content, to show a success message with the current installed version number or you can redirect after a successful installation to the page with the module settings.</translate> | ||
<translate> | <translate> | ||
| Line 737: | Line 710: | ||
</translate> | </translate> | ||
<translate><!--T:158--> The complete <tt>script.php</tt> file is as follows:</translate> | <translate><!--T:158--> The complete <tt>script.php</tt> file is as follows:</translate> | ||
< | <syntaxhighlight lang="php"> | ||
<?php | <?php | ||
/** | /** | ||
* @package [PACKAGE_NAME] | * @package [PACKAGE_NAME] | ||
| Line 750: | Line 722: | ||
* @link [AUTHOR_URL] | * @link [AUTHOR_URL] | ||
*/ | */ | ||
// No direct access to this file | // No direct access to this file | ||
defined('_JEXEC') or die; | defined('_JEXEC') or die; | ||
| Line 779: | Line 752: | ||
*/ | */ | ||
function install($parent) { | function install($parent) { | ||
echo Text::_(' | echo Text::_('MOD_FOO_INSTALLERSCRIPT_INSTALL'); | ||
return true; | return true; | ||
| Line 832: | Line 805: | ||
return false; | return false; | ||
} | } | ||
echo Text::_('MOD_FOO_INSTALLERSCRIPT_PREFLIGHT'); | echo Text::_('MOD_FOO_INSTALLERSCRIPT_PREFLIGHT'); | ||
echo $this->minimumJoomla . ' ' . $this->minimumPhp; | echo $this->minimumJoomla . ' ' . $this->minimumPhp; | ||
| Line 852: | Line 825: | ||
return true; | return true; | ||
} | } | ||
} | } | ||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
| Line 866: | Line 837: | ||
</translate> | </translate> | ||
<translate><!--T:162--> The complete <tt>language/en-GB/en-GB.mod_foo.sys.ini</tt> file is as follows:</translate> | <translate><!--T:162--> The complete <tt>language/en-GB/en-GB.mod_foo.sys.ini</tt> file is as follows:</translate> | ||
<syntaxhighlight lang="php"> | |||
MOD_FOO="[PROJECT_NAME]" | MOD_FOO="[PROJECT_NAME]" | ||
MOD_FOO_XML_DESCRIPTION="Foo Module" | MOD_FOO_XML_DESCRIPTION="Foo Module" | ||
| Line 876: | Line 846: | ||
MOD_FOO_INSTALLERSCRIPT_INSTALL="<p>The module has been installed</p>" | MOD_FOO_INSTALLERSCRIPT_INSTALL="<p>The module has been installed</p>" | ||
MOD_FOO_INSTALLERSCRIPT_POSTFLIGHT="<p>Anything here happens after the installation/update/uninstallation of the module</p>" | MOD_FOO_INSTALLERSCRIPT_POSTFLIGHT="<p>Anything here happens after the installation/update/uninstallation of the module</p>" | ||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
=== Editing mod_foo.xml === <!--T:163--> | === Editing mod_foo.xml === <!--T:163--> | ||
</translate> | </translate> | ||
<translate><!--T:164--> You have to add a line, so that the script is called automatically in Joomla.</translate> | <translate><!--T:164--> You have to add a line, so that the script is called automatically in Joomla.</translate> | ||
< | <syntaxhighlight lang="xml"><scriptfile>script.php</scriptfile></syntaxhighlight> | ||
<translate> | <translate> | ||
| Line 890: | Line 859: | ||
</translate> | </translate> | ||
<translate><!--T:166--> The complete <tt>mod_foo.xml</tt> file is as follows:</translate> | <translate><!--T:166--> The complete <tt>mod_foo.xml</tt> file is as follows:</translate> | ||
<syntaxhighlight lang="xml"> | |||
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||
<extension type="module" version="4.0" client="site" method="upgrade"> | <extension type="module" version="4.0" client="site" method="upgrade"> | ||
| Line 930: | Line 898: | ||
class="custom-select" | class="custom-select" | ||
/> | /> | ||
<field | <field | ||
name="moduleclass_sfx" | name="moduleclass_sfx" | ||
| Line 937: | Line 904: | ||
rows="3" | rows="3" | ||
/> | /> | ||
<field | <field | ||
name="cache" | name="cache" | ||
| Line 947: | Line 913: | ||
<option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option> | <option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option> | ||
</field> | </field> | ||
<field | <field | ||
name="cache_time" | name="cache_time" | ||
| Line 954: | Line 919: | ||
default="0" | default="0" | ||
/> | /> | ||
<field | <field | ||
name="cachemode" | name="cachemode" | ||
| Line 966: | Line 930: | ||
</config> | </config> | ||
</extension> | </extension> | ||
</ | </syntaxhighlight> | ||
<translate> | <translate> | ||
== Test | == Test Your Module == <!--T:167--> | ||
</translate> | </translate> | ||
<translate><!--T:168--> Now you can zip all files and install them via the Joomla Extension Manager.</translate> | <translate><!--T:168--> Now you can zip all files and install them via the Joomla Extension Manager.</translate> | ||
| Line 982: | Line 946: | ||
<translate><!--T:173--> You can find boilerplates hereː</translate> | <translate><!--T:173--> You can find boilerplates hereː</translate> | ||
* https://github.com/joomla-extensions/boilerplate/tree/master/ | * https://github.com/joomla-extensions/boilerplate/tree/master/module | ||
<translate><!--T:174--> The sample files for this Tutorial can be found hereː</translate> | <translate><!--T:174--> The sample files for this Tutorial can be found hereː</translate> | ||
* https://github.com/astridx/boilerplate/tree/tutorial/tutorial/modules | * https://github.com/astridx/boilerplate/tree/tutorial/tutorial/modules | ||
<translate> | <translate> | ||
== Use Joomla Updaterː Adding Auto Update == <!--T:175--> | |||
= Use Joomla Updaterː Adding Auto Update | |||
</translate> | </translate> | ||
| Line 994: | Line 957: | ||
=== Requirements === <!--T:176--> | === Requirements === <!--T:176--> | ||
</translate> | </translate> | ||
<translate><!--T:177--> You need Joomla! 4.x for this tutorial | <translate><!--T:177--> You need Joomla! 4.x for this tutorial.</translate> | ||
<translate> | <translate> | ||
== Joomla Updater == <!--T:178--> | === Joomla Updater === <!--T:178--> | ||
</translate> | </translate> | ||
<translate><!--T:179--> The first thing to do is to read the [[S:MyLanguage/J2.5:Managing_Component_Updates|Managing Component Upgrades with Joomla 2.5 - Part 1]] tutorial to give an idea of how the upgrade process works in | <translate><!--T:179--> The first thing to do is to read the [[S:MyLanguage/J2.5:Managing_Component_Updates|Managing Component Upgrades with Joomla 2.5 - Part 1]] tutorial to give an idea of how the upgrade process works in Joomlaǃ. Whilst written for 2.5 the process hasn't changed. Also read [[S:MyLanguage/Deploying_an_Update_Server|Deploying an update server]] - this is what we'll be implementing in this tutorial.</translate> | ||
<translate> | <translate> | ||
| Line 1,005: | Line 968: | ||
</translate> | </translate> | ||
<translate><!--T:181--> We will create/change the following files:</translate> | <translate><!--T:181--> We will create/change the following files:</translate> | ||
<translate><!--T:182--> * <tt>mod_foo.xml</tt> - The only way to update our existing module is to add in a update server - for example <tt><nowiki>http://www.example.com/foo_update. | <translate><!--T:182--> * <tt>mod_foo.xml</tt> - The only way to update our existing module is to add in a update server - for example <tt><nowiki>http://www.example.com/foo_update.xml</nowiki></tt> - into the xml file.</translate> | ||
<translate><!--T:183--> * <tt>foo_update.xml</tt> - Then we have to create the XML file for the update server at <tt><nowiki>http://www.example.com/foo_update. | <translate><!--T:183--> * <tt>foo_update.xml</tt> - Then we have to create the XML file for the update server at <tt><nowiki>http://www.example.com/foo_update.xml</nowiki></tt> to let Joomla know an update is available.</translate> | ||
<translate> | <translate> | ||
=== Editing mod_foo.xml === <!--T:184--> | ==== Editing mod_foo.xml ==== <!--T:184--> | ||
</translate> | </translate> | ||
<translate><!--T:185--> To add our update server, we need to insert the following lines in your XML- | <translate><!--T:185--> To add our update server, we need to insert the following lines in your XML-Fileː</translate> | ||
<syntaxhighlight lang="php"> | |||
<updateservers> | <updateservers> | ||
<server type="extension" priority="1" name="[PROJECT_NAME]">https://www.example.com/mod_foo.xml</server> | <server type="extension" priority="1" name="[PROJECT_NAME]">https://www.example.com/mod_foo.xml</server> | ||
</updateservers> | </updateservers> | ||
</syntaxhighlight> | |||
</ | |||
<translate> | <translate> | ||
| Line 1,025: | Line 986: | ||
</translate> | </translate> | ||
<translate><!--T:187--> The complete <tt>mod_foo.xml</tt> file is as follows:</translate> | <translate><!--T:187--> The complete <tt>mod_foo.xml</tt> file is as follows:</translate> | ||
<syntaxhighlight lang="xml"> | |||
<?xml version="1.0" encoding="utf-8"?> | <?xml version="1.0" encoding="utf-8"?> | ||
<extension type="module" version="4.0" client="site" method="upgrade"> | <extension type="module" version="4.0" client="site" method="upgrade"> | ||
| Line 1,067: | Line 1,027: | ||
class="custom-select" | class="custom-select" | ||
/> | /> | ||
<field | <field | ||
name="moduleclass_sfx" | name="moduleclass_sfx" | ||
| Line 1,074: | Line 1,033: | ||
rows="3" | rows="3" | ||
/> | /> | ||
<field | <field | ||
name="cache" | name="cache" | ||
| Line 1,084: | Line 1,042: | ||
<option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option> | <option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option> | ||
</field> | </field> | ||
<field | <field | ||
name="cache_time" | name="cache_time" | ||
| Line 1,091: | Line 1,048: | ||
default="0" | default="0" | ||
/> | /> | ||
<field | <field | ||
name="cachemode" | name="cachemode" | ||
| Line 1,103: | Line 1,059: | ||
</config> | </config> | ||
</extension> | </extension> | ||
</syntaxhighlight> | |||
<translate><!--T:188--> Now that Joomlaǃ is searching for updates to our extension, let's create one to test our process. First we need to create the file <tt>foo_update.xml</tt>. So far we have only described the update server. We do not know yet if there is an update. In the file <tt>foo_update.xml</tt> we indicate when a new version is published and where it can be downloaded.</translate> | |||
<translate><!--T:188--> | |||
<translate> | <translate> | ||
=== Creating foo_update.xml === <!--T:189--> | === Creating foo_update.xml === <!--T:189--> | ||
</translate> | </translate> | ||
<translate><!--T:190--> Now we have to create the XML file at <tt><nowiki>http://www.example.com/foo_update.xml</nowiki></tt> to let Joomla know an update is available.</translate> | <translate><!--T:190--> Now we have to create the XML file at <tt><nowiki>http://www.example.com/foo_update.xml</nowiki></tt> to let Joomla know an update is available.</translate> | ||
<translate> | <translate> | ||
==== Completed foo_update.xml ==== <!--T:191--> | ==== Completed foo_update.xml ==== <!--T:191--> | ||
</translate> | </translate> | ||
<translate><!--T:192--> The complete <tt>foo_update.xml</tt> file is as follows:</translate> | <translate><!--T:192--> The complete <tt>foo_update.xml</tt> file is as follows:</translate> | ||
<syntaxhighlight lang="xml"> | |||
<?xml version="1.0" ?> | <?xml version="1.0" ?> | ||
<updates> | <updates> | ||
<update> | <update> | ||
| Line 1,138: | Line 1,091: | ||
</update> | </update> | ||
</updates> | </updates> | ||
</syntaxhighlight> | |||
<translate><!--T:193--> After uploading this file to the address <tt><nowiki>https://www.example.com/mod_foo.xml</nowiki></tt> the update will be displayed in the Joomla Backend.</translate> | |||
<translate><!--T:193--> After uploading this file to the address <tt><nowiki>https://www.example.com/mod_foo.xml</nowiki></tt> the update will be displayed in the Joomla | |||
<translate> | <translate> | ||
== Test | === Test Your Module Update === <!--T:194--> | ||
</translate> | </translate> | ||
<translate><!--T:195--> Create a copy of the module as it is now. Then let's update the version number to 1.0.1. Now you can zip all files. After that you should load your zip to the URL <tt><nowiki>http://www.example.com/mod_foo_101.zip</nowiki></tt>. Now you can update your module via the Joomla Updater.</translate> | <translate><!--T:195--> Create a copy of the module as it is now. Then let's update the version number to 1.0.1. Now you can zip all files. After that you should load your zip to the URL <tt><nowiki>http://www.example.com/mod_foo_101.zip</nowiki></tt>. Now you can update your module via the Joomla Updater.</translate> | ||
<translate> | <translate> | ||
== Commercial Modules == <!--T:196--> | === Commercial Modules === <!--T:196--> | ||
</translate> | </translate> | ||
<translate><!--T:197--> Note that in our files we have linked to the extensions updates xml file. And from that xml file we have a location for the zip of the module. This means that if someone was to track this backwards they could find the physical source of your modules zip file. If you don't do like this, you can find a solution in this PRː https://github.com/joomla/joomla-cms/pull/15185 .</translate> | <translate><!--T:197--> Note that in our files we have linked to the extensions updates xml file. And from that xml file we have a location for the zip of the module. This means that if someone was to track this backwards they could find the physical source of your modules zip file. If you don't do like this, you can find a solution in this PRː https://github.com/joomla/joomla-cms/pull/15185 .</translate> | ||
<translate> | <translate> | ||
== Conclusion == <!--T:198--> | === Conclusion === <!--T:198--> | ||
</translate> | </translate> | ||
<translate><!--T:199--> With the | <translate><!--T:199--> With the Joomlaǃ updater, you can easily reach all users and tell them that there is a new version. Even the update itself is easy.</translate> | ||
<translate><!--T:200--> Each extension should use an update server | <translate><!--T:200--> Each extension should use an update server--especially for security reasons.</translate> | ||
<translate><!--T:201--> You can find boilerplates hereː</translate> | <translate><!--T:201--> You can find boilerplates hereː</translate> | ||
* https://github.com/joomla-extensions/boilerplate/tree/master/ | * https://github.com/joomla-extensions/boilerplate/tree/master/module | ||
<translate><!--T:202--> The sample files for this Tutorial can be found hereː</translate> | <translate><!--T:202--> The sample files for this Tutorial can be found hereː</translate> | ||
* https://github.com/astridx/boilerplate/tree/tutorial/tutorial/modules | * https://github.com/astridx/boilerplate/tree/tutorial/tutorial/modules | ||
Latest revision as of 12:23, 27 June 2024
With the move of developer documentation to the Joomla Manual, this page is unlikely to be actively maintained. A similar tutorial is available at Joomla Manual Module Development Tutorial
This is a tutorial on how to Create a simple module for Joomla Version 4x.
Introduction
Joomlaǃ 4 provides five types of extensionsː
- Components
A component is the main part of the site. A component handles data manipulation as well as input and storage into the database. A component on most sites is the primary focus of the page. - Modules
A module is an add-on to the site that extends the functionality. A module usually occupies a secondary portion of the web page and is not considered the primary focus of a page. It can be displayed on different positions and you can choose on which active menu items it should be displayed. Modules are lightweight and flexible extensions. They are used for small bits of the page that are generally less complex and are able to be seen across different components. - Plugins
A Plugin manipulates output that is already generated by the system. It typically does not run as separate part of the site. It takes data from other sources (i.e. the content) and manipulates this data before displaying. A plugin typically work behind the scenes. - Languages
Probably the most basic extensions are languages. In essence the language package files consist of key/value pairs, which provide the translation of static text strings, assigned within the Joomla! source code. - Templates
A template is basically the design of your Joomla! powered website.
Joomla! 4 is constructed using five different applications:
- Installation (used for installing Joomla and have to delete after installation)
- Administrator (Backend - used for managing content)
- Public or site (Frontend - used for displaying content)
- CLI (used for accessing Joomla on the command line and for cron jobs)
- API (web services - used for creating APIs for machine accessible content)
The installation application is used once. The administrator and public are used through the concept of components with modules. Each module has a single entry point located in the modules and accordingly administrator/modules directory. This entry point is called mod_modulename/mod_modulename.php (the mod_ prefix is a historical trace). The entry point for the login module is for example /mod_login/mod_login.php.
Requirements
You need Joomla! 4.x installation available to use for this tutorial (Download latest release here)
You can download Joomla! 4 at GitHub, on the Developer website or you can create a free website at https://launch.joomla.org.
Creating a Simple Module/Developing a Basic Module
You can see many examples of modules in the standard Joomla! install. For example:
- Menus
- Latest News
- Login form
- and many more.
This tutorial will explain how to create a simple module. Through this tutorial you will learn the basic file structure of a Joomlaǃ 4 module. This basic structure can then be expanded to produce more elaborate modules.
File Structure
There are a few basic files that are used in the standard pattern of module development:
- mod_foo.php - This file is the main entry point for the module. It will perform any necessary initialization routines, call helper routines to collect any necessary data, and include the template which will display the module output.
- mod_foo.xml - This file contains information about the module. It defines the files that need to be installed by the Joomla! installer and specifies configuration parameters for the module.
- tmpl/default.php - This is the module template. This file will take the data collected by mod_foo.php and generate the HTML to be displayed on the page.
- language/en-GB/mod_foo.ini and language/en-GB/mod_foo.sys.ini- This are the files that provide the text in United Kingdom English.
Creating mod_foo.php
The mod_foo.php file will perform following tasks:
- Import the class ModuleHelper to the current scope. We need it later for displaying the output.
- Include the template to display the output.
The helper class is imported to our current scope at the begin of the file.
use Joomla\CMS\Helper\ModuleHelper;
Last we include the template to display the output via
require ModuleHelper::getLayoutPath('mod_foo', $params->get('layout', 'default'));
Completed mod_foo.php File
The complete mod_foo.php file is as follows:
<?php
/**
* @package [PACKAGE_NAME]
*
* @author [AUTHOR] <[AUTHOR_EMAIL]>
* @copyright [COPYRIGHT]
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @link [AUTHOR_URL]
*/
// No direct access to this file
defined('_JEXEC') or die;
use Joomla\CMS\Helper\ModuleHelper;
require ModuleHelper::getLayoutPath('mod_foo', $params->get('layout', 'default'));
Side noteː In Joomla 3x you usually used a line like $moduleclass_sfx = htmlspecialchars($params->get('moduleclass_sfx'));. You don't need this anymore. See this PRː https://github.com/joomla/joomla-cms/pull/17447.
The one line that we haven’t explained so far is the first line defined('_JEXEC') or die;. This line checks to make sure that this file is being included from the Joomla application. This is necessary to prevent variable injection and other potential security concerns.
Creating tmpl/default.php
The default.php file is the template which displays the module output.
Completed tmpl/default.php file
The code for the tmpl/default.php file is as follows:
<?php
/**
* @package [PACKAGE_NAME]
*
* @author [AUTHOR] <[AUTHOR_EMAIL]>
* @copyright [COPYRIGHT]
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @link [AUTHOR_URL]
*/
// No direct access to this file
defined('_JEXEC') or die;
echo '[PROJECT_NAME]';
An important point to note is that the template file has the same scope as the mod_foo.php file. It means that a variable can be defined in the mod_foo.php file and then used in the template file without any extra declarations or function calls.
Creating mod_foo.xml
The mod_foo.xml file is the installation file. Most entries are self-explanatory.
Completed mod_foo.xml file
The code for the mod_foo.xml file is as follows:
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="4.0" client="site" method="upgrade">
<name>MOD_FOO</name>
<creationDate>[DATE]</creationDate>
<author>[AUTHOR]</author>
<authorEmail>[AUTHOR_EMAIL]</authorEmail>
<authorUrl>[AUTHOR_URL]</authorUrl>
<copyright>[COPYRIGHT]</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<version>1.0</version>
<description>MOD_FOO_XML_DESCRIPTION</description>
<files>
<filename module="mod_foo">mod_foo.php</filename>
<folder>tmpl</folder>
<folder>language</folder>
<filename>mod_foo.xml</filename>
</files>
</extension>
Creating the Language Files
The files language/en-GB/mod_foo.ini and language/en-GB/mod_foo.sys.ini are used to translate text in the Frontend and in the Backend. Note that the language file structure has been updated in Joomla 4, and language prefixes on the individual files in a language folder are no longer required.
The code for language/en-GB/mod_foo.sys.ini is as follows:
MOD_FOO="[PROJECT_NAME]"
MOD_FOO_XML_DESCRIPTION="Foo Module"
The code for language/en-GB/mod_foo.ini is as follows:
MOD_FOO="[PROJECT_NAME]"
MOD_FOO_XML_DESCRIPTION="Foo Module"
The .sys.ini file is used to translate the description of the extension upon installation, where as the .ini file is used to translate the remaining strings and the description when viewing your extension.
More information about language files can be found here.
Test Your Module
Now you can zip all files and install them via the Joomla Extension Manager.
After that you can choose your module in the module manager, when you create a new site module.


In the Frontend, you will see your module like displayed in the next image.

Conclusion
Module development for Joomla is a fairly simple, straightforward process. Using the techniques described in this tutorial, an endless variety of modules can be developed with little hassle.
You can find boilerplates hereː
The sample files for this Tutorial can be found hereː
Add a Helper Class Using Namespaces
Requirements
You need Joomla! 4.x for this tutorial.
Namespaces
With PHP 5.3, the namespaces came into their own. In other programming languages for a long time in use, these small structures now also help us with the clarity of our code.
Namespaces are separate areas in which certain logical things (in our case, classes, interfaces, functions, and constants) can live. These areas provide encapsulation of the code and prevent name conflicts.
Let's take a look how to use them in Joomla 4. We use the helper file for this.
File Structure
We will create/change the following files:
Helper/FooHelper.php- This is the file we use here as an example. We have to create it.mod_foo.php- In this file, we will mainly load the namespace.tmpl/default.php- In this file, we will demonstrate how the data of a helper can be displayed.mod_foo.xml- We create a new directory with a new file. This must be installed during the installation. For this we have to specify them in this file.
Creating Helper/FooHelper.php
Our new helper class should belong to a namespace. We achieve this with the following code. It is important, that this line is at the beginning of the file.
namespace Joomla\Module\Foo\Site\Helper;
Then we create a simple class with a simple method. Of course you can do a lot more here. Take a look at the Joomla core methods. Here are many examples. They show you first-hand what options you have.
Completed Helper/FooHelper.php
The complete FooHelper.php file is as follows:
<?php
/**
* @package Joomla.Site
* @subpackage mod_foo
*
* @copyright Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\Module\Foo\Site\Helper;
// No direct access to this file
defined('_JEXEC') or die;
/**
* Helper for mod_foo
*
* @since 4.0
*/
class FooHelper
{
/**
* Retrieve foo test
*
* @param Registry $params The module parameters
* @param CMSApplication $app The application
*
* @return array
*/
public static function getText()
{
return 'FooHelpertest';
}
}
Editing mod_foo.php
Our new helper class is imported to our current scope at the beginning of the file.
use Joomla\Module\Foo\Site\Helper\FooHelper;
Last use the helper file for testing if it is loaded correctlyː
$test = FooHelper::getText($params, $app);
Completed mod_foo.php file
The complete mod_foo.php file is as follows:
<?php
/**
* @package [PACKAGE_NAME]
*
* @author [AUTHOR] <[AUTHOR_EMAIL]>
* @copyright [COPYRIGHT]
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @link [AUTHOR_URL]
*/
// No direct access to this file
defined('_JEXEC') or die;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\Module\Foo\Site\Helper\FooHelper;
$test = FooHelper::getText();
require ModuleHelper::getLayoutPath('mod_foo', $params->get('layout', 'default'));
Editing tmpl/default.php
In this file you make only a small change to demonstrate in the Frontend that your helper file is working properly. You only add the value of the variable at the end of the current output.
echo '[PROJECT_NAME]' . $test;
Completed tmpl/default.php
The complete tmpl/default.php file is as follows:
<?php
/**
* @package [PACKAGE_NAME]
*
* @author [AUTHOR] <[AUTHOR_EMAIL]>
* @copyright [COPYRIGHT]
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @link [AUTHOR_URL]
*/
// No direct access to this file
defined('_JEXEC') or die;
echo '[PROJECT_NAME]' . $test;
Editing mod_foo.xml
First you have to add a line, so that the namespace is set automatically in Joomla. After this change, you have to re-install your module. A simple change in an already installed module is not enough. If you are doing local development you can also delete the files libraries/autoload_psr4.php and it will automatically be re-created. After inserting and installing, the namespace is known by the loader JPATH_LIBRARIES . '/autoload_psr4.php'.
<namespace>Joomla\Module\Foo</namespace>
Joomla! should copy your helper file when installing the module. So Joomla! needs to know your helper file. For this, you need to add the following line to your XML file.
<folder>Helper</folder>
Completed mod_foo.xml
The complete mod_foo.xml file is as follows:
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="4.0" client="site" method="upgrade">
<name>MOD_FOO</name>
<creationDate>[DATE]</creationDate>
<author>[AUTHOR]</author>
<authorEmail>[AUTHOR_EMAIL]</authorEmail>
<authorUrl>[AUTHOR_URL]</authorUrl>
<copyright>[COPYRIGHT]</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<version>1.0</version>
<description>MOD_FOO_XML_DESCRIPTION</description>
<namespace>Joomla\Module\Foo</namespace>
<files>
<filename module="mod_foo">mod_foo.php</filename>
<folder>tmpl</folder>
<folder>Helper</folder>
<folder>language</folder>
<filename>mod_foo.xml</filename>
</files>
</extension>
Test Your Module
Now you can zip all files and install them via the Joomla Extension Manager. After that you can choose your module in the module manager, when you create a new site module.
In the Frontend you will see your module like displayed in the next image. The text from your helper file is displayed.

Conclusion
As you can see, once you get a bit into the namespaces, they are not that complicated anymore. In big projects they can bring a lot of benefits. However, we should plan namespaces, as otherwise it will soon be more time-consuming.
You can find boilerplates hereː
The sample files for this Tutorial can be found hereː
Customizationː Add Parameters Via Form Fields
Requirements
You need Joomla! 4.x for this tutorial.
Customization with Form Fields and Parameters
Form fields give a great deal of customization in Joomla and for modules are the sole way of allowing the user to tweak the module to the needs of their site.
In this case we are going to extend our previous example using a URL field for inserting a domain that we can use as link in the front end. To allow this to happen we will use the URL Form Field type.
After that, we insert parameters that allow to use standard functionality of Joomla.
Let's take a look on how to use them in Joomla 4.
File Structure
We will change the following files:
- mod_foo.xml - This is the file where we add the fields.
- tmpl/default.php - In this file demonstrate how the data of a field can be used.
- language/en-GB/en-GB.mod_foo.ini - Here we use a language string so that the field can be labeled correctly in different languages.
Editing mod_foo.xml
First we set a custom parameter.
<field
name="domain"
type="url"
label="MOD_FOO_FIELD_URL_LABEL"
filter="url"
/>
Then we insert Joomla default fields, so that we can use cache, moduleclass-suffix and layouts.
<field
name="layout"
type="modulelayout"
label="JFIELD_ALT_LAYOUT_LABEL"
class="custom-select"
/>
<field
name="moduleclass_sfx"
type="textarea"
label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
rows="3"
/>
<field
name="cache"
type="list"
label="COM_MODULES_FIELD_CACHING_LABEL"
default="0"
>
<option value="1">JGLOBAL_USE_GLOBAL</option>
<option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option>
</field>
<field
name="cache_time"
type="number"
label="COM_MODULES_FIELD_CACHE_TIME_LABEL"
default="0"
/>
<field
name="cachemode"
type="hidden"
default="itemid"
>
<option value="itemid"></option>
</field>
Completed mod_foo.xml
The complete mod_foo.xml file is as follows:
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="4.0" client="site" method="upgrade">
<name>MOD_FOO</name>
<creationDate>[DATE]</creationDate>
<author>[AUTHOR]</author>
<authorEmail>[AUTHOR_EMAIL]</authorEmail>
<authorUrl>[AUTHOR_URL]</authorUrl>
<copyright>[COPYRIGHT]</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<version>1.0</version>
<description>MOD_FOO_XML_DESCRIPTION</description>
<namespace>Joomla\Module\Foo</namespace>
<files>
<filename module="mod_foo">mod_foo.php</filename>
<folder>tmpl</folder>
<folder>Helper</folder>
<folder>language</folder>
<filename>mod_foo.xml</filename>
</files>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="domain"
type="url"
label="MOD_FOO_FIELD_URL_LABEL"
filter="url"
/>
</fieldset>
<fieldset name="advanced">
<field
name="layout"
type="modulelayout"
label="JFIELD_ALT_LAYOUT_LABEL"
class="custom-select"
/>
<field
name="moduleclass_sfx"
type="textarea"
label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
rows="3"
/>
<field
name="cache"
type="list"
label="COM_MODULES_FIELD_CACHING_LABEL"
default="0"
>
<option value="1">JGLOBAL_USE_GLOBAL</option>
<option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option>
</field>
<field
name="cache_time"
type="number"
label="COM_MODULES_FIELD_CACHE_TIME_LABEL"
default="0"
/>
<field
name="cachemode"
type="hidden"
default="itemid"
>
<option value="itemid"></option>
</field>
</fieldset>
</fields>
</config>
</extension>
Editing tmpl/default.php
We can use the value of the parameter for creating a hyperlink in the Frontend. We can access the value via the variable $params.
$domain = $params->get('domain', 'https://www.joomla.org');
Later we set use this value for creating the hyperlink.
<a href="<?php echo $domain; ?>">
<?php echo '[PROJECT_NAME]' . $test; ?>
</a>
Completed tmpl/default.php file
The complete tmpl/default.php file is as follows:
<?php
/**
* @package [PACKAGE_NAME]
*
* @author [AUTHOR] <[AUTHOR_EMAIL]>
* @copyright [COPYRIGHT]
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @link [AUTHOR_URL]
*/
// No direct access to this file
defined('_JEXEC') or die;
$domain = $params->get('domain', 'https://www.joomla.org');
?>
<a href="<?php echo $domain; ?>">
<?php echo '[PROJECT_NAME]' . $test; ?>
</a>
Editing language/en-GB/en-GB.mod_foo.ini
Here we can specify the text for the English version of the field label.
MOD_FOO_FIELD_URL_LABEL="Url"
Completed language/en-GB/en-GB.mod_foo.ini
The complete language/en-GB/en-GB.mod_foo.ini file is as follows:
MOD_FOO="[PROJECT_NAME]"
MOD_FOO_XML_DESCRIPTION="Foo Module"
MOD_FOO_FIELD_URL_LABEL="Url"
Test Your Module
Now you can zip all files and install them via the Joomla Extension Manager. After that you can choose your module in the module manager, when you create a new site module.
In the Backend, you will see your module like displayed in the next image.
In the basic tab, you will see the custom field where you can insert a domain. The text for the label is fetched from the language file.

In the advanced tab, you will see all default options except the cache mode because of this is a hidden field.

In the Frontend, you will see your module like displayed in the next image. The text form your helper file is displayed and you should see a hyperlink.

Conclusion
Form fields give the user an easy way to customize the module to their sites settings. This allows the modules scope to be increased.
You can find boilerplates hereː
The sample files for this Tutorial can be found hereː
See this issue for possible future changes:
Use Install, Update and Uninstall Script
Requirements
You need Joomla! 4.x for this tutorial.
Scripts
Installing, updating and uninstalling a module may require additional operations that cannot be achieved by the basic operations described in the main XML file. Joomla offers a new approach to solve this problem. It consists in using a PHP script file containing a class using five methods:
- preflight which is executed before install and update
- install
- update
- uninstall
- postflight which is executed after install and update
Let's take a look how to use them in Joomla 4. We use the helper file for this.
File Structure
We will create/change the following files:
- script.php - This is the file we use here as an example. We have to create it.
- language/en-GB/en-GB.mod_foo.sys.ini - In this file we will add text.
- mod_foo.xml - We create a new file. This must be installed during the installation. For this we have to specify it in this file.
Creating script.php
Writing an extension script consists in declaring a class whose name is mod_ModuleNameInstallerScript with these 5 methods. See the comments in the file for more information. In this comments I explain when a method is called.
In this example, I only use text to show when which method will be executed. In addition, I show you how to check the minimum requirements. Of course you can do much more. For example, you can delete files that are no longer needed in a new version of your module. This can be seen in the file. Another idea for this file is to create sample content, to show a success message with the current installed version number or you can redirect after a successful installation to the page with the module settings.
Completed script.php
The complete script.php file is as follows:
<?php
/**
* @package [PACKAGE_NAME]
*
* @author [AUTHOR] <[AUTHOR_EMAIL]>
* @copyright [COPYRIGHT]
* @license GNU General Public License version 2 or later; see LICENSE.txt
* @link [AUTHOR_URL]
*/
// No direct access to this file
defined('_JEXEC') or die;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Log\Log;
/**
* Script file of Foo module
*/
class mod_fooInstallerScript {
/**
* Extension script constructor.
*
* @return void
*/
public function __construct() {
$this->minimumJoomla = '4.0';
$this->minimumPhp = JOOMLA_MINIMUM_PHP;
}
/**
* Method to install the extension
*
* @param InstallerAdapter $parent The class calling this method
*
* @return boolean True on success
*/
function install($parent) {
echo Text::_('MOD_FOO_INSTALLERSCRIPT_INSTALL');
return true;
}
/**
* Method to uninstall the extension
*
* @param InstallerAdapter $parent The class calling this method
*
* @return boolean True on success
*/
function uninstall($parent) {
echo Text::_('MOD_FOO_INSTALLERSCRIPT_UNINSTALL');
return true;
}
/**
* Method to update the extension
*
* @param InstallerAdapter $parent The class calling this method
*
* @return boolean True on success
*/
function update($parent) {
echo Text::_('MOD_FOO_INSTALLERSCRIPT_UPDATE');
return true;
}
/**
* Function called before extension installation/update/removal procedure commences
*
* @param string $type The type of change (install, update or discover_install, not uninstall)
* @param InstallerAdapter $parent The class calling this method
*
* @return boolean True on success
*/
function preflight($type, $parent) {
// Check for the minimum PHP version before continuing
if (!empty($this->minimumPhp) && version_compare(PHP_VERSION, $this->minimumPhp, '<')) {
Log::add(Text::sprintf('JLIB_INSTALLER_MINIMUM_PHP', $this->minimumPhp), Log::WARNING, 'jerror');
return false;
}
// Check for the minimum Joomla version before continuing
if (!empty($this->minimumJoomla) && version_compare(JVERSION, $this->minimumJoomla, '<')) {
Log::add(Text::sprintf('JLIB_INSTALLER_MINIMUM_JOOMLA', $this->minimumJoomla), Log::WARNING, 'jerror');
return false;
}
echo Text::_('MOD_FOO_INSTALLERSCRIPT_PREFLIGHT');
echo $this->minimumJoomla . ' ' . $this->minimumPhp;
return true;
}
/**
* Function called after extension installation/update/removal procedure commences
*
* @param string $type The type of change (install, update or discover_install, not uninstall)
* @param InstallerAdapter $parent The class calling this method
*
* @return boolean True on success
*/
function postflight($type, $parent) {
echo Text::_('MOD_FOO_INSTALLERSCRIPT_POSTFLIGHT');
return true;
}
}
Editing language/en-GB/en-GB.mod_foo.sys.ini
There is not much to explain here. Write the text for the translation into this file.
Completed language/en-GB/en-GB.mod_foo.sys.ini file
The complete language/en-GB/en-GB.mod_foo.sys.ini file is as follows:
MOD_FOO="[PROJECT_NAME]"
MOD_FOO_XML_DESCRIPTION="Foo Module"
MOD_FOO_INSTALLERSCRIPT_PREFLIGHT="<p>Anything here happens before the installation/update/uninstallation of the module</p>"
MOD_FOO_INSTALLERSCRIPT_UPDATE="<p>The module has been updated</p>"
MOD_FOO_INSTALLERSCRIPT_UNINSTALL="<p>The module has been uninstalled</p>"
MOD_FOO_INSTALLERSCRIPT_INSTALL="<p>The module has been installed</p>"
MOD_FOO_INSTALLERSCRIPT_POSTFLIGHT="<p>Anything here happens after the installation/update/uninstallation of the module</p>"
Editing mod_foo.xml
You have to add a line, so that the script is called automatically in Joomla.
<scriptfile>script.php</scriptfile>
Completed mod_foo.xml
The complete mod_foo.xml file is as follows:
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="4.0" client="site" method="upgrade">
<name>MOD_FOO</name>
<creationDate>[DATE]</creationDate>
<author>[AUTHOR]</author>
<authorEmail>[AUTHOR_EMAIL]</authorEmail>
<authorUrl>[AUTHOR_URL]</authorUrl>
<copyright>[COPYRIGHT]</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<version>1.0</version>
<description>MOD_FOO_XML_DESCRIPTION</description>
<namespace>Joomla\Module\Foo</namespace>
<scriptfile>script.php</scriptfile>
<files>
<filename module="mod_foo">mod_foo.php</filename>
<folder>tmpl</folder>
<folder>Helper</folder>
<folder>language</folder>
<filename>mod_foo.xml</filename>
</files>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="domain"
type="url"
label="MOD_FOO_FIELD_URL_LABEL"
filter="url"
/>
</fieldset>
<fieldset name="advanced">
<field
name="layout"
type="modulelayout"
label="JFIELD_ALT_LAYOUT_LABEL"
class="custom-select"
/>
<field
name="moduleclass_sfx"
type="textarea"
label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
rows="3"
/>
<field
name="cache"
type="list"
label="COM_MODULES_FIELD_CACHING_LABEL"
default="0"
>
<option value="1">JGLOBAL_USE_GLOBAL</option>
<option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option>
</field>
<field
name="cache_time"
type="number"
label="COM_MODULES_FIELD_CACHE_TIME_LABEL"
default="0"
/>
<field
name="cachemode"
type="hidden"
default="itemid"
>
<option value="itemid"></option>
</field>
</fieldset>
</fields>
</config>
</extension>
Test Your Module
Now you can zip all files and install them via the Joomla Extension Manager. Immediately after the installation, you will see the following information. This you had entered in the script so.

Conclusion
As you can see, Joomla offers you a lot to make your extension easy to use - right from the start.
You can find boilerplates hereː
The sample files for this Tutorial can be found hereː
Use Joomla Updaterː Adding Auto Update
Requirements
You need Joomla! 4.x for this tutorial.
Joomla Updater
The first thing to do is to read the Managing Component Upgrades with Joomla 2.5 - Part 1 tutorial to give an idea of how the upgrade process works in Joomlaǃ. Whilst written for 2.5 the process hasn't changed. Also read Deploying an update server - this is what we'll be implementing in this tutorial.
File Structure
We will create/change the following files:
- mod_foo.xml - The only way to update our existing module is to add in a update server - for example http://www.example.com/foo_update.xml - into the xml file.
- foo_update.xml - Then we have to create the XML file for the update server at http://www.example.com/foo_update.xml to let Joomla know an update is available.
Editing mod_foo.xml
To add our update server, we need to insert the following lines in your XML-Fileː
<updateservers>
<server type="extension" priority="1" name="[PROJECT_NAME]">https://www.example.com/mod_foo.xml</server>
</updateservers>
Completed mod_foo.xml
The complete mod_foo.xml file is as follows:
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="4.0" client="site" method="upgrade">
<name>MOD_FOO</name>
<creationDate>[DATE]</creationDate>
<author>[AUTHOR]</author>
<authorEmail>[AUTHOR_EMAIL]</authorEmail>
<authorUrl>[AUTHOR_URL]</authorUrl>
<copyright>[COPYRIGHT]</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<version>1.0</version>
<description>MOD_FOO_XML_DESCRIPTION</description>
<namespace>Joomla\Module\Foo</namespace>
<files>
<filename module="mod_foo">mod_foo.php</filename>
<folder>tmpl</folder>
<folder>Helper</folder>
<folder>language</folder>
<filename>mod_foo.xml</filename>
</files>
<updateservers>
<server type="extension" priority="1" name="[PROJECT_NAME]">https://www.example.com/mod_foo.xml</server>
</updateservers>
<config>
<fields name="params">
<fieldset name="basic">
<field
name="domain"
type="url"
label="MOD_FOO_FIELD_URL_LABEL"
filter="url"
/>
</fieldset>
<fieldset name="advanced">
<field
name="layout"
type="modulelayout"
label="JFIELD_ALT_LAYOUT_LABEL"
class="custom-select"
/>
<field
name="moduleclass_sfx"
type="textarea"
label="COM_MODULES_FIELD_MODULECLASS_SFX_LABEL"
rows="3"
/>
<field
name="cache"
type="list"
label="COM_MODULES_FIELD_CACHING_LABEL"
default="0"
>
<option value="1">JGLOBAL_USE_GLOBAL</option>
<option value="0">COM_MODULES_FIELD_VALUE_NOCACHING</option>
</field>
<field
name="cache_time"
type="number"
label="COM_MODULES_FIELD_CACHE_TIME_LABEL"
default="0"
/>
<field
name="cachemode"
type="hidden"
default="itemid"
>
<option value="itemid"></option>
</field>
</fieldset>
</fields>
</config>
</extension>
Now that Joomlaǃ is searching for updates to our extension, let's create one to test our process. First we need to create the file foo_update.xml. So far we have only described the update server. We do not know yet if there is an update. In the file foo_update.xml we indicate when a new version is published and where it can be downloaded.
Creating foo_update.xml
Now we have to create the XML file at http://www.example.com/foo_update.xml to let Joomla know an update is available.
Completed foo_update.xml
The complete foo_update.xml file is as follows:
<?xml version="1.0" ?>
<updates>
<update>
<name>Foo</name>
<description>This is mod_foo 1.0.1</description>
<element>mod_foo</element>
<type>module</type>
<version>1.0.1</version>
<downloads>
<downloadurl type="full" format="zip">http://www.example.com/mod_foo_101.zip</downloadurl>
</downloads>
<maintainer>Joomla</maintainer>
<maintainerurl>http://www.example.com</maintainerurl>
<targetplatform name="joomla" version="4.0"/>
<client>site</client>
</update>
</updates>
After uploading this file to the address https://www.example.com/mod_foo.xml the update will be displayed in the Joomla Backend.
Test Your Module Update
Create a copy of the module as it is now. Then let's update the version number to 1.0.1. Now you can zip all files. After that you should load your zip to the URL http://www.example.com/mod_foo_101.zip. Now you can update your module via the Joomla Updater.
Commercial Modules
Note that in our files we have linked to the extensions updates xml file. And from that xml file we have a location for the zip of the module. This means that if someone was to track this backwards they could find the physical source of your modules zip file. If you don't do like this, you can find a solution in this PRː https://github.com/joomla/joomla-cms/pull/15185 .
Conclusion
With the Joomlaǃ updater, you can easily reach all users and tell them that there is a new version. Even the update itself is easy.
Each extension should use an update server--especially for security reasons.
You can find boilerplates hereː
The sample files for this Tutorial can be found hereː