If you are new to Joomla, please read Absolute basics of how a component works[^docs.joomla.org/Absolute_Basics_of_How_a_Component_Functions].

This tutorial is intended for Joomla 4. For information on creating a component for Joomla 3, see Developing a Model View Controller Component / 3.x[^docs.joomla.org/J3.x:Developing_an_MVC_Component].

You need Joomla 4.x for this tutorial. You can find Joomla 4 on GitHub[^github.com/joomla/joomla-cms] on the Developer Website[^developer.joomla.org/nightly-builds.html] or create a free website at launch.joomla.org.

Aim of this tutorial?

This tutorial does not create a practical example. I have intentionally kept everything general. My main goal is to show you how Joomla works - and to help you understand it better yourself. In the end, you replace the name 'foo' in all files with the name of your component and extend it with your special requirements. If you like, you can use the script duplicate.sh[^github.com/astridx/boilerplate/blob/t43/duplicate.sh] for this.

Therefore, this tutorial is primarily intended for programmers who want to create a new component and do not know Joomla yet. The tutorial is also a help for programmers of a Joomla 3 component, if they extend their component for Joomla 4. For example, if you are working on validating your Joomla 3 component, you will find what you need in the chapters on server-side and client-side validation - no more and no less.

The structure of this tutorial

Each chapter builds on the previous builds. However, if you are interested in a specific topic, feel free to look at a separate chapter. Be aware, however, that elements integrated in a previous chapter may be necessary.

Why this structure? There are many examples of components in the standard Joomla. For example

  • com_content
  • com_banner
  • com_tags or
  • com_contact

In each component you see implementation details in context. Each is complex and finding and separating certain elements, such as page numbering or custom fields, is a hassle. This tutorial focuses on one detail per chapter.

You create a component for Joomla 4, reusing the many existing implementations in Joomla. You are not reinventing the wheel. Joomla offers a whole range of standard functions.

If you want to get started immediately, scroll to The first view in the backend. Below you will find some things about Joomla 4 that you do not necessarily need for editing. However, some of them are good to know.


Joomla 4 offers five types of extensions

  • Components: A component fills the main content of the site. It usually uses data that is stored in the database.
  • Modules: A module is an add-on to the site that extends the functionality. It has a secondary part on the web page and is displayed at different positions. It is selectable on which active menu elements it is displayed. Modules are light and flexible extensions. They are used for small parts of the page that are less complex and are displayed across different components.
  • Plugins: A plugin processes the output generated by the system. It is not normally called as a separate part of the site. It takes data from other sources and manipulates it before output. A plugin works in the background.
  • Languages: The most basic extensions are languages. Essentially, language package files consist of key/value pairs that allow the translation of static text strings in the Joomla source code.
  • Templates: A template defines the design of your Joomla website.

Joomla 4 consists of five different applications

  • Installation (used to install Joomla and must be deleted after installation);
  • Administrator (backend - to manage content);
  • Website (frontend - used to display content);
  • CLI (used to access Joomla from the command line and for cron jobs);
  • API (Web Services - used to create APIs for machine-accessible content);

Basic knowledge

Development environment

This text is about the Joomla code. It is not about the latest tools for developers. However, a few things are essential.

Test environment

You want to program an extension for Joomla and therefore need an environment in which Joomla is installed. In my opinion, a XAMPP server package[^www.apachefriends.org/index.html] on a local workstation is an ideal prerequisite for developing new extensions. The direct access to the files of Joomla in the local file system facilitates the handling.

Code editors or IDE

A good editor is also essential. This should be one you feel comfortable with. Wikipedia maintains a list of editors.[^en.wikipedia.org/wiki/List_of_text_editors].

More convenience is offered by an integrated development environment IDE. By convenience I mean functions like

  • versioning: integration of GIT[^wikipedia.org/wiki/Git]
  • Code completion: Complement user input in a meaningful way
  • Syntax highlighting: colour highlighting of variables, class names or statements.
  • Coding standards: Observance of rules
  • Debugging: Finding errors

You can also get an overview of IDEs from Wikipedia using a List of IDEs[^en.wikipedia.org/wiki/Comparison_of_integrated_development_environments].

In the Joomla community, the IDE PHPStorm[^www.jetbrains.com/phpstorm/], which is subject to a fee, is popular. Users of Visual Studio Code[^code.visualstudio.com/] are becoming increasingly common. Also worth mentioning are NetBeans and Eclipse.

Are you looking for instructions on how to set up the development environment? Joomla with Visual Studio Code can be found in the Joomla Documentation[^docs.joomla.org/Visual_Studio_Code]. For PHPStorm, Jetbrains provides a description.

If you like, you can read my first steps with Visual Studio Code at blog.astrid-guenther.de/ubuntu-vscode-docker-lamp.

Joomla 3 and Joomla 4 in comparison

New in Joomla 4

Frontend and Backend accessible and with Bootstrap 5

Joomla 4 integrates Bootstrap 5 into the Joomla core. Thereby, the included templates are accessible and correspond to level AA of WCAG 2.1. WCAG 2.1 complements WCAG 2.0 and is the web standard for digital accessibility, which is mandatory for public bodies in the European Union. As an extension developer, it is not mandatory that you use Bootstrap 5. But technically it should comply with the latest standards. It would be a shame not to use the good template that Joomla offers.

Optimised Web Assets

With a single call, Web Assets allow developers to load multiple Javascript and CSS files in a specified order. For example, if an extension developer uses styles that depend on Font Awesome being loaded first and they know that Joomla 4 uses the icon font set, Web Assets come into play. Web Assets are described in several places in this tutorial.

Use the Web Asset Manager when developing for Joomla 4. All calls to HTMLHelper::_('stylesheet or script ...) work, but these assets are appended after the Web Asset Manager assets. This results in overriding styles that are set in the template. Thus, a user does not have the possibility to manipulate by means of a user.css. See in this context (Issue 35706)https://github.com/joomla/joomla-cms/issues/35706.

Web Services enable automated data exchange

Joomla 4 web services make content accessible to other websites or mobile applications. What is a web service? Different definitions cause confusion. The SOAP standards are referred to as web services. Others know them under the term REST API. The W3C generally defines a web service as an interface for automated communication via computer networks. The API integration in Joomla 4 implements such an interface in the core of the CMS with the help of REST. In the example we are building in this text, we also support the Joomla API.


With the new Workflow component, it is possible to link website content to a workflow. Thirt Party extensions can also offer a workflow with the core extension. This function is not yet included here in the book.

Many other changes and improvements

Joomla 4 includes new security features such as support for prepared statements for database systems. This prevents SQL injection because the database checks the validity of parameters. In addition, the code base has been restructured. The code was thoroughly cleaned up, obsolete functions removed and PHP namespaces introduced.

Backwards compatibility with Joomla 3

This text is primarily written for developers who are starting a new extension. Nevertheless, issues related to compatibility with Joomla 3 are of interest. A page in the Joomla documentation[^docs.joomla.org/Potential_backward_compatibility_issues_in_Joomla_4] summarises the important points.

Never change the core files

The purpose of Joomla extensions is to have a system that can be extended. It is possible that your code and Joomla Core code can be provided with new functions independently of each other.

If make changes to Joomla itself, these will be overwritten with the next update.

You have the feeling that your function can only be implemented with a core hack? Your feeling is wrong! There is always a solution that leaves the system files untouched.

Learn from the core files

That you should not change the system files does not mean that you do not even look at them. Quite the opposite! By reading you will come across lots of code that is not documented anywhere. If you are not sure how to best implement a function, just rummage around in the Joomla code. The solution is usually be found in the heart of Joomla.

The autoload_psr4.php file

During the installation, entries are made in /administrator/ cache/autoload_psr4.php. This is new in Joomla 4. If you encounter strange problems, delete this file. It will be recreated the next time you load. Sometimes this solves a problem.

The following text was added to the README on Github[^github.com/joomla/joomla-cms/pull/28436/files] using the PR 28436[^github.com/joomla/joomla-cms/blob/4.0-dev/readme.md]: "Joomla creates a cache of the namespaces of its extensions in JOOMLA_ROOT/administrator/ cache/autoload_psr4.php. If extensions are created, deleted or removed in git then this file needs to be recreated. You can simply delete the file and it will be regenerated on the next call to Joomla."


Note the namespace entry at the top of most PHP files.

Namespace FooNamespace\ Component\Foos\Administrator\View\Foos;

and as a tag in the manifest file

<Namespace>FooNamespace\ Component\Foos</ Namespace>.

Remember to include the path="src" parameter if you put the namespace files in the src subdirectory. This is common in Joomla and the sample extensions created in this tutorial also use this directory[github.com/astridx/boilerplate/blob/62a970704ee2899addd3922e88c918b7f6af72a2/ src/administrator/components/com_foos/foos.xml#L12].

Why use namespaces? All PHP classes are thus organised in a defined structure and automatically loaded via the Classloader. Thereby ContentModelArticles becomes Joomla\Component\Content\ Administrator\Model\ArticlesModel.

JLoader can process the namespaces automatically and distinguishes between front-end and back-end classes.

Files with namespaces can be found in the directory /src[^github.com/joomla/joomla-cms/pull/27687]

Capitalisation of folder and file names

You will notice that some of the Joomla 4 folder and file names start with upper case letters and others with lower case letters. At first glance, this seems unstructured. At second glance it makes sense.

The folders in upper case contain PHP classes with namespace. Those in lower case contain XML files, template files. There are a few lower case folders that contain PHP files. These are necessary to ensure compatibility with Joomla 3. Often these are helper files.

For more information, see: github.com/joomla/joomla-cms/issues/22990.

Meaningful class names

The component MVC classes have more meaningful names in Joomla 4. For example, the controllers now have controller as a suffix for their class name. Thus, FooNamespace\Component\Foos\ Administrator\Controller\Foos becomes FooNamespace\Component\Foos\ Administrator\Controller\ FoosController.

Additionally, the default controller, which in Joomla 3 is just called Controller, gets the name DisplayController to better reflect what the class does. See: https://github.com/joomla/joomla-cms/pull/17624


Do you need an empty file index.html in each folder of your component? The index.html is no longer needed, as that is directory listings not allowed in the default configuration[^github.com/joomla/joomla-cms/pull/4171]. If you are further interested read the discussion on the topic in the Google Group[^groups.google.com/forum/#!topic/joomla-dev-cms/en1G7QoUW2s].

Technical requirements

Do you know how those responsible at Joomla decide which functions are supported and what is not pursued further? That's what the statistics plugin[^developer.joomla.org/about/stats.html] is for. Thanks to the users who activate this extension, important information flows into the development.

Why is a blank line inserted at the end of a source code file in Joomla files?

There are several reasons why a blank line at the end of a file is included as a requirement in the Joomla Coding Standards:

  • Apart from the fact that it is a nicer cursor position when you go to the end of a file in a text editor, a line break at the end of the file allows you to easily check that the file has not been truncated.
  • When you paste something at the end of a file, the difference display in Git shows that you've changed the last line, when the only thing you've actually pasted is a line break. This is confusing.
  • Today it doesn't matter, but: many older tools in the programming field misbehave if the last line of data in a file is not terminated with a newline or a carriage return/newline combination.


Why should you omit the closing tag of PHP sections at the end of a file?

The closing tag of a PHP block at the end of a file is optional, and in some cases it is helpful to omit it. By omitting the closing tag, you can avoid accidentally inserting spaces or line breaks at the end of the file. For further explanation, see php.net[php.net/basic-syntax.instruction-separation].

PHP operators for equality (== two equal signs) and identity (=== three equal signs)

The [comparison operator](https://www.php.net /manual/en/language.operators.comparison.php #language.operators.comparison)[php.net/manual/en/language.operators.comparison.php #language.operators.comparison] == compares between two different types if they are different, while the === operator performs a type-safe comparison. This means that it returns true only if both operands have the same type and the same value. Examples:

1 === 1: true 1 == 1: true 1 === "1": false // 1 is an integer, "1" is a string 1 == "1": true // "1" is converted to an integer, which is 1 "foo" === "foo": true // both operands are strings and have the same value

Note: Two instances of the same class with equivalent elements will be evaluated by the operator with three equal signs === with false. Example:

$a = new stdClass();
$a->foo = "bar";
$b = clone $a;
var_dump($a === $b); // bool(false)

In Joomla, we use type-safe comparison whenever possible because it is more accurate.

Single quotes and double quotes

Single quotes

The simplest way to specify a string is to enclose it in single quotes. Single quotes are generally faster, and anything enclosed in quotes is treated as a single string. Example:

echo 'Start with a single string';
echo 'String with an apostrophe';
echo 'String with a php variable'.$name;
Double quotes

Use double quotes in PHP to avoid using a period when separating. Use curly braces {} in strings to enclose variables if you don't like to use the concatenation operator (.). Example:

var $name = "Peter";
echo "Hello {$name}"

In Joomla we use single quotes when possible. Using single quotes is slightly faster. PHP does not need any additional processing to interpret what is inside the single quote. If you use double quotes, PHP needs to check if there are any variables in the string.

More information about this and the explanation of two other ways to use strings in PHP can be found on the website php.net[^php.net/manual/en/language.types.string.php].

Alternative syntax for control structures

PHP offers an additional notation for control structures. This is especially handy when outputting larger blocks of HTML directly - without using echo. Use them in template files. This way they remain clear.


<?php foreach ($this->items as $i => $item) : ?>
<?php echo $item->name; ?>
<?php endforeach; ?>

instead of

foreach ($this->items as $i => $item) {
	echo $item->name;
	echo '</br>';

In this way, a single line is self-contained and the HTML code is still clearly structured.

Database table prefix

As an extension developer, you ideally develop your extension so that the database prefix is variable. For this purpose, one uses the string #__. The string #__ is replaced with the correct prefix at runtime by Joomla.

JavaScript, CSS and image files?

Where do you best store JavaScript, CSS and image files? Store these data in the directory media in the Joomla root directory. This way it is possible to overwrite them. This is particularly advantageous for CSS files to make the design of the whole Joomla Website consistent. The Best Practice Guidelines[^docs.joomla.org/Development_Best_Practices] also recommend this.

Examples: For this tutorial extension I will later use media/com_foos/js/ for the JavaScript files of the component. The CSS files of the module mod_articles_news can be found in the directory media/mod_articles_news/css/. And the images for the plugin plg_content_vote are in the folder media/plg_content_vote/images/.

Fontawesome Icons

You want to use icons but don't want to add your own library. Use the free icons from fontawesome.com/icons in the frontend and backend. At least if you use the standard templates Cassiopeia and Atum, this will work. If your template does not support FontAwesome, you can load the icons yourself via the WebassetManager. In Joomla Fontawesome is delivered with the template. Marking them as dependency[^templates/cassiopeia/joomla.asset.json] is sufficient.

Attention: In Joomla Core files, you cannot simply copy them, because Joomla add the text icon- in front of the icon name. This is then converted via the file build/media_source/ system/scss/_icomoon.scss[^github.com/joomla/joomla-cms/blob/4.0-dev/build/media_source/system/scss/_icomoon.scss or media/system/scss/_icomoon.scss] for Fontawesome. In this way, only the icons included in the previously mentioned file will work. Why does Joomla complicate the selection of Font Awesome icons? The reason for this is as follows: Extensions that were programmed for Joomla 3 can still be used.

The HTML code

<i class="fas fa-align-left"></i>

displays the left-aligned character, for example.

Use images

A new JLayout[^gist.github.com/dgrammatiko/a20236039586a2fbc5c77caadffc3de8] as of Joomla 4.0.5 allows developers to output HTML image tags easily:

So instead of writing something like this:


'; ?>

The recommended way is to use the JLayout:

echo LayoutHelper::render('joomla.html.image', ['src' => imageURL, 'alt' => $imageAlt]);


  • The URL and the alt attribute are escaped correctly.
  • The developer does not have to worry about the "#" at the end of the URL.
  • The image tag gets a loading="lazy" attribute if the image has the width and height attributes defined.
  • The alt attribute is ignored if the value passed is false.
  • All other attributes are rendered correctly, pass them as in the array (for example 'class' => 'my-class').