As we saw earlier in the lifetime of a component, the Extension class of a component is sort of a service locator for our component. Joomla checks if that objects implements a PHP Interface it knows about and uses the service communicated via the Interface implementation (typically one of the corresponding PHP Traits provided by Joomla) to do something useful, e.g. register an HTMLHelper helper, integrate with Tags, create SEF URLs by using a Router and so on and so forth.
If your component does not make use of any of these features you do
not need to create a custom extension class for your component. Joomla
gives you the perfectly serviceable
Joomla\CMS\Extension\MVCComponent
class which implements a
minimal Joomla 4 component: it can run because it returns a Dispatcher and
it can create MVC objects using the Joomla 4 MVC because it returns an
MVCFactory object. This is enough for a component which only runs in the
backend or runs in both the frontend and the backend but has no way of
letting Joomla create SEF URLs for it. You may think this is useless but
I'd contest you're not thinking simple enough. Case in point, some core
Joomla components doing exactly that. For example the
com_actionlogs
component which only has a backend user
interface.
That said, there wouldn't be much to write if all or even most components didn't need a custom extension class. You see, most components need one or more of the following features. I am documenting the features I discovered that need customisations in the extension class and give you an overview of the required changes in your component's code to make them work.
-
Use a custom HTML Helper.
Your extension class must implement the
Joomla\CMS\HTML\HTMLRegistryAwareInterface
and use theJoomla\CMS\HTML\HTMLRegistryAwareTrait
. The extension class must override theboot
method and have a line similar to$this->getRegistry()->register('something', new MyHTMLHelper())
. We'll see what that means in the section covering the HTML helper. -
Use core categories.
Your extension class must implement the
Joomla\CMS\Categories\CategoryServiceInterface
and use theJoomla\CMS\Categories\CategoryServiceTrait
. Your service provider (provider.php
) needs to register aJoomla\CMS\Extension\Service\Provider\CategoryFactory
service provider and use the extension object'ssetCategoryFactory
method to pass this factory to the extension object. The extension class must override thegetTableNameForSection
andgetStateColumnForSection
methods defined in the aforementioned trait and interface. -
Integrate with Joomla's Tags feature.
Your extension class must implement the
Joomla\CMS\Tag\TagServiceInterface
and use theJoomla\CMS\Tag\TagServiceTrait
. The extension class must override thegetTableNameForSection
andgetStateColumnForSection
methods defined in the aforementioned trait and interface. -
Integrate with Joomla's Custom Fields feature.
Your extension class must implement the
Joomla\CMS\Fields\FieldsServiceInterface
. The extension class must implement thevalidateSection
andgetContext
methods defined in the aforementioned interface. -
Provide a Router for meaningful, human-readable SEF URLs in the frontend.
Your component must have a class implementing the
Joomla\CMS\Component\Router\RouterFactoryInterface
(Router factory) and a class implementing theJoomla\DI\ServiceProviderInterface
(Router factory provider). Your extension class must implement theJoomla\CMS\Component\Router\RouterServiceInterface
and use theJoomla\CMS\Component\Router\RouterServiceTrait
. Your service provider (provider.php
) needs to register your Router factory provider and use the extension object'ssetRouterFactory
method to pass the resulting Router factory to the extension object. -
Let Joomla associate items between languages on multi-language sites.
Your component must have a class extending the
Joomla\CMS\Association\AssociationExtensionHelper
. Your service provider (provider.php
) must register this class with theJoomla\CMS\Association\AssociationExtensionInterface::class
key and use the extension object'ssetAssociationExtension
method to assign the object resulting from that service to the extension object. Your extension object needs to implement theJoomla\CMS\Association\AssociationServiceInterface
and use theJoomla\CMS\Association\AssociationServiceTrait
. -
Integrate with Joomla's Workflows feature.
Your extension class must implement the
Joomla\CMS\Workflow\WorkflowServiceInterface
and use theJoomla\CMS\Workflow\WorkflowServiceTrait
. The extension class must override thegetModelName
,filterTransitions
,getWorkflowTableBySection
,getWorkflowContexts
andgetCategoryWorkflowContext
methods defined in the aforementioned trait and interface.
As you can see, trying to do pretty much anything useful does require a custom extension class.
There are no hard rules for naming your component's extension
class. That said, to help anyone reading your code — including yourself
six or so months later — retain a modicum of their sanity it is
advisable to use the convention
\
where:My
\Component\ComponentName
\Administrator\Extension\ComponentName
+Component
-
\
is the namespace prefix of your component, for instanceMy
\Component\ComponentName
\Acme\Component\Example
-
is the name of your component without theComponentName
com_
prefix, with the first letter in uppercase, for instanceExample
for componentcom_example
-
Component
is the literal "Component". With
we mean a concatenation of the component name and the literal string "Component", for instanceComponentName
+ComponentExampleComponent
for componentcom_example
For example, if you have a component named
com_example
with the namespace prefix
\Acme\Component\Example
your extension class
should be
\Acme\Component\Example\Administrator\Extension\ExampleComponent
and placed in the file
administrator/components/com_example/src/Extension/ExampleComponent.php
.