Fixing the hot mess of class and file naming in component's MVC was one of the priorities in Joomla 4. Having a CMS in 2020 (when Joomla 4 was released) still use a half-finished and proven problematic architecture from 2006 would just not cut it.
The first step was to add namespaces and make sure that the folder and file names follow the PSR-4 standard.
Your component's namespace prefix is declared in the XML manifest
of the component using a new XML element under the
<extension>
root element:
<namespace path="src">Acme\Component\Example</namespace>
The path
attribute tells Joomla which subdirectory of
your extension holds the PSR-4 of your extension's PHP files. It is best
practice to name it src
but you don't
have to. I always assume you are using
src
.
The text inside the XML element,
Acme\Component\Example
in our example, is the namespace
prefix you will be using. Each component has its own namespace prefix,
which consists of 3 parts:
\
.
For instance (as often used throughout this book)
My
\Component\ComponentName
\Acme\Component\Example
.
The 3 parts of a component namespace prefix are as follows:
-
The vendor namespace prefix: a valid PHP namespace, unique for you, your company or your project. A valid vendor namespace prefix can for instance be
\Acme
. A vendor namespace prefix can also have sub-namespaces, for instance:\Acme\Support\Tools
. You are free to choose your own vendor namespace, however:-
The vendor namespace should not start with
\Joomla
, because component namespaces starting withIn\Joomla
are reserved for core components. -
The vendor namespace should not contain a sub-namespace starting with
\Component
. It is a reserved sub-namespace, that should only be used immediately AFTER the vendor namespace prefix in a component namespace.
-
-
The literal string
Component
, with a capital C. You should use the\Component
sub-namespace in the component namespace only once, to separate the vendor namespace prefix from the component's sub-namespace i.e. after the vendor namespace and before the sub-namespace with the component name. -
The component sub-namespace: a valid component name for Joomla as is used in
com_componentname
. In simple terms, it's the same as your component's folder name, without thecom_
prefix. You can optionally use camel case in your sub-namespace. However, you can only use lowercase in your component name and folder name (everywhere you have to usecom_componentname
). A valid component sub-namepsacewould for instance beExample
in the namespaceAcme\Component\Example
for componentcom_example
.
Note that this component namespace is the common namespace prefix for your entire component. Your component has a different namespace suffix for each of the three web applications in Joomla: frontend (site), backend (administrator) and api (the brand-new JSON API; this is optional).
Here is how namespace prefixes work across the three Joomla
applications, assuming a common namespace prefix
Acme\Component\Example
:
-
Component, frontend. The frontend classes MUST be under the namespace
\Acme\Component\Example\Site
. The foldercomponents/com_example/src
is the root of the\Acme\Component\Example\Site
namespace. -
Component, backend. The backend classes MUST be under the namespace
\Acme\Component\Example\Administrator
. The folderadministrator/components/com_example/src
is the root of the\Acme\Component\Example\Administrator
namespace. -
Component, API application. The API application classes MUST be under the namespace
\Acme\Component\Example\Api
. The folderapi/components/com_example/src
is the root of the\Acme\Component\Example\Api
namespace.
Please note that you do not get a special namespace to use for the Joomla Console (CLI) application. You will be reusing the classes from the other three Joomla applications.
Class names are different than, but not a huge departure from, what you had in Joomla 3.
In Joomla 4 and beyond the naming convention for controllers,
models and tables is
\
where:NamespacePrefix
\ApplicationType
\Type
\Name
Type
-
NamespacePrefix
is your common namespace prefix, e.g.\Acme\Component\Example
. -
ApplicationType
is the type of the application part of your component i.e. one ofSite
(frontend),Administrator
(backend), orApi
(JSON API application). -
Name
is the name of the specific MVC class with its first letter in uppercase, e.g.Item
. -
Type
is the type of the class you have, i.e. one ofController
,Model
, orTable
. Again, the first letter is uppercase.
All of your classes need to be placed inside the folder you have
declared in your XML manifest as your namespace root folder, typically
src
. The files and folders under it follow the PSR-4 naming
standard. Assuming that you have a component called
com_example
, with a namespace prefix
Acme\Component\Example
and a namespace root
folder called src
, the backend model class
\Acme\Component\Example\Administrator\Model\ItemModel
can be found in the file
administrator/components/com_example/src/Model/ItemModel.php
.
Views have a very slightly different convention because we also
have the view type. Their naming convention is
\
where:NamespacePrefix
\ApplicationType
\View\Name
\ViewType
-
NamespacePrefix
is your common component namespace prefix, e.g.\Acme\Component\Example
. -
ApplicationType
is the type of the application part of your component i.e. one ofSite
(frontend),Administrator
(backend), orApi
(JSON API application). -
Name
is the name of the specific MVC class with its first letter in uppercase, e.g.Item
. -
ViewType
corresponds to the format URL parameter with its first letter in uppercase, e.g.Html
,Json
,Feed
,Raw
and so on.
The HTML view class for a view called item
of the
hypothetical component we discussed above would have the fully qualified
class name
\Acme\Component\Example\Administrator\View\Item\HtmlView
and you would find it in the file
administrator/components/com_example/src/View/Item/HtmlView.php
.
Right away you can see how namespaces are benefiting us. A controller, model, or view in the frontend, backend and api application have a different FQN (Fully Qualified Name). They no longer have the same name. One can extend the other if we want to, we can mix front-, backend and api MVC objects if we need to and all of these classes can be autoloaded without having to use weird static calls. Cool!